viewWillDisappear is not called - ios

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.

Related

How prepareForSegue works?

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.

Hide the ViewController till the webView is loaded (till the delegate method is called)

I have a UIWebView as a subview in ViewController i present modally, I want to present the view controller only after the WebView is loaded.
How should i approach this? I was thinking about delegation/block callback but then the viewController wont be even called,
I'm looking for a way to hide the ViewController till the delegate method "webViewDidFinishLoad" is called
Thanks for the help !
You can use a Container View to contain ViewController B. It will be called when entering ViewController A. When webViewDidFinishLoad in ViewController B is triggered you can set containerView.alpha = 1;

UIPopoverController delegate not getting called on dismiss

I assign popover object o it's contentViewController and I put dismiss code in a button which resides in the content view controller.
When the button is pressed:
[self.popover dismissPopoverAnimated:YES];
is called and popover is dismissed.
However, delegate's method is not called automatically. I thought that I was not setting it's delegate, but it is there. If I add the following line after dismissPopoverAnimated line, delegate is called correctly...
[self.popover.delegate popoverControllerDidDismissPopover:self.popover];
I don't understand why it doesn't "automatically" call the delegate's method.
How can this happen?
The popoverControllerDidDismissPopover: in the delegate is not called when 'dismissPopoverAnimated:' is used.
From the Apple Documentation for popoverControllerDidDismissPopover: in UIPopoverControllerDelegate:
The popover controller does not call this method in response to programmatic calls to the dismissPopoverAnimated: method. If you dismiss the popover programmatically, you should perform any cleanup actions immediately after calling the dismissPopoverAnimated: method.
There are two ways to dismiss a popover. (a) tapping outside the popover; and (b) doing it programmatically with
[self.popover dismissPopoverAnimated:YES];
If you do it programmatically, then the docs (https://developer.apple.com/library/ios/documentation/uikit/reference/UIPopoverControllerDelegate_protocol/Reference/Reference.html#//apple_ref/occ/intfm/UIPopoverControllerDelegate/popoverControllerDidDismissPopover:) say:
The popover controller does not call this method in response to
programmatic calls to the dismissPopoverAnimated: method. If you
dismiss the popover programmatically, you should perform any cleanup
actions immediately after calling the dismissPopoverAnimated: method.
Thus, not calling the delegate automatically is the normal behavior, and what you're doing (calling it yourself) is fine.
popoverControllerDidDismissPopover is not called on Dismiss, but its called when you click outside the popoverController contentview.
https://developer.apple.com/library/ios/documentation/uikit/reference/UIPopoverControllerDelegate_protocol/Reference/Reference.html#jumpTo_4

How do I tell why my UIViewController is disappearing?

My UIViewController is in a navigation stack. How can I detect when the user is trying to pop up to a previous level vs. pushing a new view controller over it?
I want to post a notification when the view is removed from the stack, as if the user had tapped a Save button that I don't have.
If you're using a UINavigationController, then UINavigationBarDelegate is the delegate class and it implements the following methods.
Pushing Items
– navigationBar:shouldPushItem:
– navigationBar:didPushItem:
Popping Items
– navigationBar:shouldPopItem:
– navigationBar:didPopItem:
You can put code in these method that you want to be executed when the view is popped from the stack.
You could do something in viewWillDisappear: and there is also the UINavigationControllerDelegate protocol that has two methods for detecting when views will or have been shown.

How can I add and remove notification observers when a UIViewController is pushed/pulled by a navigation controller?

I usually add the UINotification observer in the init method and I remove them in dealloc.
However if I have a chain of UIViewControllers pushed by a UINavigationController, they are not deallocated when the next UIViewController is pushed. Consequently they all observe for the notification, and this is not what I want.
How can I add and remove notification observers when a UIViewController is pushed/pulled by a navigation controller ?
In order to get notified, you can set the delegate of the UINavigationController. This is quite cumbersome though, since the navigation controller only has one delegate. So in this case, I would have used viewDidAppear:animated, viewDidDisappear:animated and so on. These methods will be called on your view controllers as the navigation controller hides and shows them, and will also be called if you present a modal view controller in which case you probably also want to unregister notifications.
Adding a second answer with an example on how to achieve this with a UINavigationControllerDelegate.
Somewhere, set the delegate to the root view controller. Either with code or by connecting it in a nib. Make your root view controller a UINavigationControllerDelegate.
#interface MyViewController : UIViewController <UINavigationControllerDelegate>
// ...
#end
Do this in the implementation of the root view controller
#implementation MyViewController
- (void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController
animated:(BOOL)animated
{
[viewController
performSelector:#selector(willBeShownViaNavigationController)];
[navigationController.visibleViewController
performSelector:#selector(willBeHiddenViaNavigationController)];
}
#end
Make sure all the view controllers being used in that navigation controller implements those two methods.
Note: this code is untested, there may be some errors. But you should get the idea.
You need to subclass UINavigationController to keep track of whether it is pushing or popping. Then in your viewWillAppear you can check to see if you're being pushed or popped. I have a subclass for that Here

Resources