What is the easiest way to force a crash in Swift?
I would like to use only one line of code (something that I can add quickly).
I don't want to use breakpoints, I actually want the app to crash.
iosipadiphonemacosswift
What is the easiest way to force a crash in Swift?
I would like to use only one line of code (something that I can add quickly).
I don't want to use breakpoints, I actually want the app to crash.
You will only need a ScrollView
if the contents you have now do not fit in the iPhone screen. (If you are adding the ScrollView
as the superview of the components just to make the TextField
scroll up when keyboard comes up, then it's not needed.)
The standard way to prevent the TextField
s from being covered by the keyboard is to move the view up/down whenever the keyboard is shown.
Here is some sample code:
#define kOFFSET_FOR_KEYBOARD 80.0
-(void)keyboardWillShow {
// Animate the current view out of the way
if (self.view.frame.origin.y >= 0)
{
[self setViewMovedUp:YES];
}
else if (self.view.frame.origin.y < 0)
{
[self setViewMovedUp:NO];
}
}
-(void)keyboardWillHide {
if (self.view.frame.origin.y >= 0)
{
[self setViewMovedUp:YES];
}
else if (self.view.frame.origin.y < 0)
{
[self setViewMovedUp:NO];
}
}
-(void)textFieldDidBeginEditing:(UITextField *)sender
{
if ([sender isEqual:mailTf])
{
//move the main view, so that the keyboard does not hide it.
if (self.view.frame.origin.y >= 0)
{
[self setViewMovedUp:YES];
}
}
}
//method to move the view up/down whenever the keyboard is shown/dismissed
-(void)setViewMovedUp:(BOOL)movedUp
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3]; // if you want to slide up the view
CGRect rect = self.view.frame;
if (movedUp)
{
// 1. move the view's origin up so that the text field that will be hidden come above the keyboard
// 2. increase the size of the view so that the area behind the keyboard is covered up.
rect.origin.y -= kOFFSET_FOR_KEYBOARD;
rect.size.height += kOFFSET_FOR_KEYBOARD;
}
else
{
// revert back to the normal state.
rect.origin.y += kOFFSET_FOR_KEYBOARD;
rect.size.height -= kOFFSET_FOR_KEYBOARD;
}
self.view.frame = rect;
[UIView commitAnimations];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// register for keyboard notifications
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide)
name:UIKeyboardWillHideNotification
object:nil];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
// unregister for keyboard notifications while not visible.
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillHideNotification
object:nil];
}
This question seems to be very popular here on Stack Overflow so I thought I would try and give a better answer to help out people starting in the world of iOS like me.
I hope this answer is clear enough for people to understand and that I have not missed anything.
Passing Data Forward
Passing data forward to a view controller from another view controller. You would use this method if you wanted to pass an object/value from one view controller to another view controller that you may be pushing on to a navigation stack.
For this example, we will have ViewControllerA
and ViewControllerB
To pass a BOOL
value from ViewControllerA
to ViewControllerB
we would do the following.
in ViewControllerB.h
create a property for the BOOL
@property (nonatomic, assign) BOOL isSomethingEnabled;
in ViewControllerA
you need to tell it about ViewControllerB
so use an
#import "ViewControllerB.h"
Then where you want to load the view, for example, didSelectRowAtIndex
or some IBAction
, you need to set the property in ViewControllerB
before you push it onto the navigation stack.
ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNib:@"ViewControllerB" bundle:nil];
viewControllerB.isSomethingEnabled = YES;
[self pushViewController:viewControllerB animated:YES];
This will set isSomethingEnabled
in ViewControllerB
to BOOL
value YES
.
Passing Data Forward using Segues
If you are using Storyboards you are most likely using segues and will need this procedure to pass data forward. This is similar to the above but instead of passing the data before you push the view controller, you use a method called
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
So to pass a BOOL
from ViewControllerA
to ViewControllerB
we would do the following:
in ViewControllerB.h
create a property for the BOOL
@property (nonatomic, assign) BOOL isSomethingEnabled;
in ViewControllerA
you need to tell it about ViewControllerB
, so use an
#import "ViewControllerB.h"
Create the segue from ViewControllerA
to ViewControllerB
on the storyboard and give it an identifier. In this example we'll call it "showDetailSegue"
Next, we need to add the method to ViewControllerA
that is called when any segue is performed. Because of this we need to detect which segue was called and then do something. In our example, we will check for "showDetailSegue"
and if that's performed, we will pass our BOOL
value to ViewControllerB
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:@"showDetailSegue"]){
ViewControllerB *controller = (ViewControllerB *)segue.destinationViewController;
controller.isSomethingEnabled = YES;
}
}
If you have your views embedded in a navigation controller, you need to change the method above slightly to the following
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:@"showDetailSegue"]){
UINavigationController *navController = (UINavigationController *)segue.destinationViewController;
ViewControllerB *controller = (ViewControllerB *)navController.topViewController;
controller.isSomethingEnabled = YES;
}
}
This will set isSomethingEnabled
in ViewControllerB
to BOOL
value YES
.
Passing Data Back
To pass data back from ViewControllerB
to ViewControllerA
you need to use Protocols and Delegates or Blocks, the latter can be used as a loosely coupled mechanism for callbacks.
To do this we will make ViewControllerA
a delegate of ViewControllerB
. This allows ViewControllerB
to send a message back to ViewControllerA
enabling us to send data back.
For ViewControllerA
to be a delegate of ViewControllerB
it must conform to ViewControllerB
's protocol which we have to specify. This tells ViewControllerA
which methods it must implement.
In ViewControllerB.h
, below the #import
, but above @interface
you specify the protocol.
@class ViewControllerB;
@protocol ViewControllerBDelegate <NSObject>
- (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item;
@end
Next still in the ViewControllerB.h
, you need to set up a delegate
property and synthesize in ViewControllerB.m
@property (nonatomic, weak) id <ViewControllerBDelegate> delegate;
In ViewControllerB
we call a message on the delegate
when we pop the view controller.
NSString *itemToPassBack = @"Pass this value back to ViewControllerA";
[self.delegate addItemViewController:self didFinishEnteringItem:itemToPassBack];
That's it for ViewControllerB
. Now in ViewControllerA.h
, tell ViewControllerA
to import ViewControllerB
and conform to its protocol.
#import "ViewControllerB.h"
@interface ViewControllerA : UIViewController <ViewControllerBDelegate>
In ViewControllerA.m
implement the following method from our protocol
- (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item
{
NSLog(@"This was returned from ViewControllerB %@", item);
}
Before pushing viewControllerB
to navigation stack we need to tell ViewControllerB
that ViewControllerA
is its delegate, otherwise we will get an error.
ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNib:@"ViewControllerB" bundle:nil];
viewControllerB.delegate = self
[[self navigationController] pushViewController:viewControllerB animated:YES];
NSNotification center
It's another way to pass data.
// Add an observer in controller(s) where you want to receive data
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleDeepLinking:) name:@"handleDeepLinking" object:nil];
-(void) handleDeepLinking:(NSNotification *) notification {
id someObject = notification.object // Some custom object that was passed with notification fire.
}
// Post notification
id someObject;
[NSNotificationCenter.defaultCenter postNotificationName:@"handleDeepLinking" object:someObject];
Passing Data back from one class to another (A class can be any controller, Network/session manager, UIView subclass or any other class)
Blocks are anonymous functions.
This example passes data from Controller B to Controller A
Define a block
@property void(^selectedVoucherBlock)(NSString *); // in ContollerA.h
Add block handler (listener)
Where you need a value (for example, you need your API response in ControllerA or you need ContorllerB data on A)
// In ContollerA.m
- (void)viewDidLoad {
[super viewDidLoad];
__unsafe_unretained typeof(self) weakSelf = self;
self.selectedVoucherBlock = ^(NSString *voucher) {
weakSelf->someLabel.text = voucher;
};
}
Go to Controller B
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
ControllerB *vc = [storyboard instantiateViewControllerWithIdentifier:@"ControllerB"];
vc.sourceVC = self;
[self.navigationController pushViewController:vc animated:NO];
Fire block
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:
(NSIndexPath *)indexPath {
NSString *voucher = vouchersArray[indexPath.row];
if (sourceVC.selectVoucherBlock) {
sourceVC.selectVoucherBlock(voucher);
}
[self.navigationController popToViewController:sourceVC animated:YES];
}
Best Answer
Typically you'd use
or
for that.
These do exactly the same: terminating the program, therefore the code after this stamement never gets executed. All of the functions that have this behaviour are annotated with the
@noreturn
attributeYou can also do something like this:
The function is supposed to return an Int, but because the program never gets to that point, you don't have to return anything.