Viewdiddisappear Not Called When Use Presentviewcontroller

viewDidDisappear not called when use presentViewController

That is the correct behavior. Here's an excerpt about viewWillDisappear: from the UIViewController API docs:

This method is called in response to a view being removed from a view hierarchy. This method is called before the view is actually removed and before any animations are configured.

Presenting a new view controller so that it hides the other view controller doesn't count as the view disappearing—only actually being removed from a view hierarchy does (e.g., with something like popViewControllerAnimated:).

viewDidAppear and viewDidDisappear not called when modalPresentationStyle=UIModalPresentationCustom

This is the correct behaviour as presenting a new view controller only hides the presenting view controller. It doesn't add the view to the hierarchy when the presented view controller is dismissed, and it doesn't remove the presenting view controller view from the hierarchy when the view controller that is presented is presented.

Short story; it hides the view of the presenting view controller instead of removing it. Therefore the methods aren't invoked.

viewDidAppear: called when using presentViewController:animated:completion:

The answer to which you linked is about the behavior of viewDidDisappear, not viewDidAppear. The note in the documentation you linked says that viewDidAppear will not be called on the presenting view controller when a child view controller presented with a popover is dismissed.

In your case you are presenting the child view controller without a popover, so I read the doc's note (in an "exception that proves the rule" way) as saying that viewDidAppear should be called on the presenting view controller when the child view controller is dismissed in your case.

I think you should be seeing viewDidDisappear called on your parent view controller when the child view controller is presented. I tried this out in a minimal test app, using this code to present a child view controller:

Parent *parent = [[Parent alloc] initWithNibName:nil bundle:nil];
[self.window setRootViewController:parent];
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
Child *child = [[Child alloc] initWithNibName:nil bundle:nil];
[parent presentViewController:child animated:YES completion:^{
NSLog(@"Child presented");
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[parent dismissViewControllerAnimated:YES completion:^{
NSLog(@"Child dismissed");
}];
});
}];
});

and, logging the calls to the various appearance related callbacks in both the Parent and Child class. This is the sequence I see:

Making the parent view controller the root view controller:

Parent viewWillAppear:
Parent viewDidAppear:

Presenting the child view controller:

Parent viewWillDisappear:
Child viewWillAppear:
Child viewDidAppear:
Parent viewDidDisappear:
Child presented

Dismissing the child view controller:

Child viewWillDisappear:
Parent viewWillAppear:
Parent viewDidAppear:
Child viewDidDisappear:
Child dismissed

So this seems internally consistent to me---the parent gets the disappearance calls when the child view controller is presented and the appearance calls when the child view controller is dismissed. And this is still consistent with the documented behavior of viewWillAppear because I'm not presenting the child view controller with a popover.

I'm afraid I don't know why you're not getting the viewWill/DidDisappear calls when your child view controller is presented.

viewDidDisappear not called

I finally asked Apple Technical support the same question. They concluded that this was a bug in iOS, so I have filed a bug report to Apple. The same bug seems to appear in iOS 6 and in the latest iOS 7 (Beta 5).

Apple Technical Support suggested the following:

As a workaround, you can move your cleanup code to a separate method
which the AppDelegate would then invoke on the navigation controller's
top view controller, before it pops the entire navigation stack.

However, I think this exposes too much of my details in the view controller, so I chose to implement it using willMoveToParentViewController: instead. This method is called when the view controller is removed from its parent, and it is called properly.

Swift viewWillAppear not being called after dismissing view controller

You need to set the correct presentationStyle. If you want that your presentedController will be fullScreen and call it the previous viewWillAppear, then you can use ".fullScreen"

let viewController = self.storyboard?.instantiateViewController(withIdentifier: "LoginController") as! LoginController

let navigationController: UINavigationController = UINavigationController(rootViewController: viewController)

navigationController.modalPresentationStyle = .fullScreen

present(navigationController, animated: true, completion: nil)

Issue with calling viewWillAppear of presenting view controller when presented one is dismissed

bhalla,

Two ways,

Way 1

You can make use of delegates and protocol for this :)

Declare a protocol in BVC and confirm it in AVC. And when you are done in BVC call the method of protocol and let the AVC dismiss BVC and by doing that you can pass the data from BVC to AVC as well.

Example :

Declare a protocol like the one below in BVC

protocol letsCallParent{
func amDoneHere(dataIwantToPass : String)
}

Declare a property to hold the reference of view controller confirming to this protocol in BVC

var myParent : letsCallParent?

And when you are done with BVC and you have to dismiss youself call the method in delegate and pass the data you want to pass :) Now it would be good coding practice to expect the parent (AVC) to dismiss BVC rather then call dismissViewController on self :)

if let parent = myParent {
parent.amDoneHere("Hi am Done here")
}

In AVC confirm to the protocol using

class AVC: UIViewController,letsCallParent{

and after instantiating BVC before presenting it assign the self as myParent of BVC :)

let bvc: BVC = sb.instantiateViewControllerWithIdentifier("BVC") as! BVC
bvc.myParent = self

and finally implement the protocol method :)

func amDoneHere(dataIwantToPass: String) {
print("\(dataIwantToPass)")
//if you want to dismiss BVC call
//if you have pushed bvc
//self.navigationController?.popToViewController(self, animated: true)
//if you have presented
//self.dismissViewControllerAnimated(true, completion: nil)
}

WAY 2

Make use of unwind segue :) making use of unwind segue will eliminate the need to write delegate and protocols and all :) also provides the parent view controller an opportunity to access the child view controller as well :)
Once you have an access to child VC which is BVC you can read the data from it :)

Example :

Declare an unwind segue :)
If you want BVC to call a metod of AVC when it gets dimissed, declare a unwind segue method in AVC :)

@IBAction func cancelChildVC(segue:UIStoryboardSegue) {
let childVC : SecondViewController = segue.sourceViewController as! SecondViewController
print(childVC.name)
self.dismissViewControllerAnimated(true, completion: nil)
}

The signature of the method is fixed :) It has to be a @IBAction and it has to accept segue as paramter :)

Only after declaring this method :) go to your story board and select the BVC and hold control and drag from the button or any other view you have in BVC to dismiss it, to Exit option in BVC :)

Have look at gif provided below for clear understanding :)

Sample Image

If you do it correctly you will see the method that you have declared in AVC coming up as pop up option :) select it :) Thats it :) Whenever you tap on the button or the view from which you have dragged the control to Exit, the method in your AVC gets called :)

In AVC's method you can access the BVC instance because now you have the access to segue instance :) remember prepareForSegue method for direct segues, this is similar to that for unwind segue :)

let childVC : SecondViewController = segue.sourceViewController as! SecondViewController
print(childVC.name)
self.dismissViewControllerAnimated(true, completion: nil)

Notice the usage of "segue.sourceViewController" once you have the acces to BVC access its data :)

Hope my answer helped :)



Related Topics



Leave a reply



Submit