How prepareForSegue works? - ios

I am curious about this method
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender;
I find this method in UIViewController.h, and it's a regular method.
I check it, it is not a delegate method (it is not a protocol).
Because UITableViewController extends from UIViewController, we can use this method in our custom class for any table views.
Strangely, this method behaves like a delegate, it fires without any calls.
It fires when the view is going to do a transition.
As far as I know, this behaviour only exist in delegation.
How can a UIViewController calls prepareForSegue method in it's child class?

prepareForSegue is a method that is called as and when a transition is going to occur between ViewControllers. So, whenever a segue is made, this method will be called mandatorily. Now if your main View has a subclassed View and you want to perform a Segue from it, you can do it using the following function.
[self performSegueWithIdentifier:#"segueIdentifier" sender:self];
In this case, this method will invoke a transition with the specified identifier which corresponds to a segue. And whenever this method is called, prepareForSegue is called immediately after this, after which transition occurs.
For information, it is better to connect segue between ViewControllers rather than creating segue directly from Controls in the view. As sometimes, some conditions need to be checked before performing a Segue.
Hope this helps.

Like many other methods of UIViewController, your subclass can override the default behavior of many UIViewController methods. A couple of examples include viewDidLoad and viewWillAppear.

Related

Segue related functions

I know, I can programmtically do segue action by using:
-performSegueWithIdentifier:sender:
I also know the other segue related method on UIViewController, -prepareForSegue:sender:, in which I can do customization on the destination view controller.
But I am wondering, which one is called first?
say in a scenario, there is ViewControllerOne that has a button which triggers the -performSegueWithIdentifier:sender: , then goes to ViewControllerTwo.
The first is performSegueWithIdentifier:sender: and actually this is the one you performed.
The second call you mentioned prepareForSegue:sender: is a delegate call, which you are not forced to implement
Got it myself:
Before performSegueWithIdentifier
Before prepareForSegue
After prepareForSegue.
After performSegueWithIdentifier

Call delegate when user tap "Back" button

I need a way to change text depending of user input, when user tap back button. I followed that solution: Find out if user pressed the back button in uinavigationcontroller?
and did add following code in viewDidLoad:
if ([self isMovingFromParentViewController]) {
NSLog(#"isMoved");
[self.delegate stringChangedTo:self.myTextField.text atIndex:self.indexToPass];
}
However, nothing changed. More to say, method is not called (NSLog dont output a string).
How could i find a way to call delegate when user tap back button?
That code needs to be in viewWillDisappear: or viewDidDisappear:. not viewDidLoad.
viewDidLoad is called when the view controller's view is loaded. You want to call the delegate when the view controller is being dismissed.
There is also a UINavigationControllerDelegate protocol. You can get notified when a given view controller is shown by implementing either of these:
-navigationController:willShowViewController:animated:
-navigationController:didShowViewController:animated:
ADDENDUM:
In my opinion, using the delegate is a cleaner design, because you get notified precisely when a navigation event occurs. View controller life cycle methods such as -viewDidDisappear:, etc. can get called when you present/dismiss a modal view controller, and require that you add logic to discern those.

Custom UIStoryboardSegue using segueWithIdentifier:source:destination:performHandler:

I am trying to use a custom UIStoryboardSegue to implement a transition between two view controllers. I can do this by subclassing UIStoryboardSegue, and then setting this class in IB. However, I was looking at the docs which say:
If your segue does not need to store additional information or provide anything other than a perform method, consider using the segueWithIdentifier:source:destination:performHandler: method instead.
Implying that you don't need to create the custom subclass, just use the custom performHandler.
I am confused as to where this code should go, and how I go about using it. Do I create the segue as normal in IB and then override that before it is fired (maybe in shouldPerformSegue: or similar). Elsewhere in apple's documentation it says:
Your app never creates segue objects directly; they are always created on your behalf by iOS when a segue is triggered
So I don't quite understand why they are then saying to instantiate a segue using a class creator method.
The point of segueWithIdentifier:source:destination:performHandler:
Provide an alternative to UIViewController performSegueWithIdentifier:sender in cases where you also want to create a custom transition, without creating a segue subclass.
Vend a segue that can be used as the return for segueForUnwindingToViewController:fromViewController:identifier
As noted above, this approach is only viable for segues which you would call manually -- i.e. not for segues that would otherwise be triggered via IB triggers.
So, for example, if you have a segue that needs to be triggered after a certain timeout period (such as a custom lock-screen), you could use segueWithIdentifier:source:destination:performHandler: to handle the custom transition.
-(void)appTimeoutLockScreen
{
UIStoryboardSegue *segue =
[UIStoryboardSegue segueWithIdentifier:#"LockScreenSegue"
source:sourceVC
destination:destinationVC
performHandler:^{
// transition code that would
// normally go in the perform method
}];
// Dev is responsible for calling prepareForSegue and perform.
// Note, the order of calls for an IB triggered segue as well as
// a performSegueWithIdentifier segue is perform first, then
// prepareForSegue:sender. Manual segues need to inverse the call
// in order to ensure VC setup is finished before transition.
[self prepareForSegue:segue sender:self];
[segue perform];
}
Another practical use for the method is unwinding segues. Using a similar scenario
to the previous example, we could use it to return a segue to transition from a lock screen back to the previous viewController:
-(UIStoryboardSegue *)segueForUnwindingToViewController:(UIViewController*)toVC
fromViewController:(UIViewController *)fmVC
identifier:(NSString *)identifier
{
UIStoryboardSegue *segue =
[UIStoryboardSegue segueWithIdentifier:#"FromLockScreenSegue"
source:fmVC
destination:toVC
performHandler:^{
// transition code
}];
return segue;
}

viewWillDisappear is not called

I'm using a navigationController in my app. One UI i have tried to click one button (Not in Navigation bar) viewWillDisappear is not called. But i'm not using the navigationController it's calling the viewWillDisappear. Can you please help me how to call the viewWillDisappear with a navigationController?
So, first of all - (void)viewWillDisappear:(BOOL)animated is a method specific to UIViewController class.
Second, this method shouldn't be called directly from the code, this method is called automatically when a UIViewController is removed from a view hierarchy. (check UIViewController specs)
So in order to handle this method call, you have to implement it in your custom UIViewController class (do not forget to call [super viewWillDisappear:animated]). Whenever your custom UIViewController view will disappear from the screen (is popped from the stack or other UIViewController is added to the stack) this method will be called.

Understanding/clarifying view controller syntax

I've been looking at view controllers for a few days now (searching xcode help, google and stack overflow), and I think I have some understanding of it, but not a lot.
I have some code, that I have trouble understanding.
So here I have the following code I found in the book I'm reading, and I'm not sure If I understand it correctly.
-(void)prepareForSegue(UIStoryboardsegue *)segue sender:(id)sender{
((ViewController2 *)segue.destinationViewController).delegate = self;
}
First, I have no idea why we typecast to our second view controller(viewController2) here.
I think I get the rest though, we take the method's segue parameter (which holds information about the view controllers involved in the segue), and we access the destinationViewController(meaning that we want to access the view controller that we are going to). We then set the delegate property of the destination view controller to self. I believe we set the delegate property to self, because we want to send messages to a delegate in the view controller we're going to.
Heres the last one I don't get:
In the header file:
#property (weak, nonatomic)id delegate;
In the implementation file: (the controllerVisisble property is a boolean, and is changed to YES when the user hits a button to perform a manual segue to the second view controller, which is this one)
-(void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
((ViewController *)self.delegate).controllerrVisisble=NO;
}
Heres what I think this does: the viewWillDisappear method is called when a view is closing/removed.
I'm not quite sure about [super viewWillDisappear:animated], but I'm guessing that it gives an animation when the view disappears?However, I remove that line, and my dismissViewControllerAnimated method still gives an animation when the view controller is dismissed.
Here's the part that really confuses me. We need to access the first view controllers dateChooserVisible property somehow, to set it to NO, so we can access the second view controller again through our button. But, I don't understand why we have to typecast (viewController *), and type in self.delegate. Nor, do I understand why we created a property called delegate in the header file, to use here.
A lot of these questions are more generic than just within the context of view controllers.
[super methodName] calls the superclasses implementation of the method named methodName. In your case, Apple has written some code (that we don't have access to) in UIViewController's viewWillDisappear: method. ALWAYS call super when overriding a method from a superclass.
Note that viewWillDisappear: is just callback triggered whenever the view is set to disappear. My guess is that the super implementation of this method forwards this callback down to child view controllers, especially in the case of standard container classes like UINavigationController and UITabBarController.
The type casting really doesn't seem necessary, you can always call methods without compiler errors/warnings if the receiver is either type id or provides a declaration for the called method in its #interface.
As far as the delegates go, protocols and delegation are a major part of Objective-C, and widely used in Apple's APIs. This link might help you understand how they work; it helped me immensely.

Resources