Trigger events when ViewController covered by a presented ViewController

3k Views Asked by At

I would like to process code when a ViewController is no longer visible due to presenting a new ViewController.

I cannot use ViewWillDisappear etc since the controller is not technically ever dismissed from the stack - you just can't see it.

What process can I use so that code runs when the controller is no longer visible (i.e. topmost) and when it becomes visible again?

EDIT: Seems some confusion here - not sure why. I have a viewcontroller. I use the following code to present another controller

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let navController = storyboard.instantiateViewControllerWithIdentifier("NavController") as! UINavigationController
let thisController = navController.viewControllers[0] as! MyController
self.presentViewController(navController, animated: true, completion: nil)

This controller does not trigger a viewWillDisappear on the previous controller since the previous view is not removed - just hidden.

I need to process code when this view is hidden (i.e. not visible) and, more importantly, process code when it becomes visible again.

3

There are 3 best solutions below

0
On BEST ANSWER

When presenting a UIViewController if the presentation style has been set to UIModalPresentationOverCurrentContext it doesn't call the viewWillDisappear and related methods as the view never disappears or gets hidden.

A simple test to check if thats the case would be to set the NavController that you are using to have a clear background color. If you do this and present the NavController and you can still view the first UIViewController below your NavController content. Then you are using UIModalPresentationOverCurrentContext and that is why the viewDidDisappear isn't called.

Have a look at the answer referenced by Serghei Catraniuc (https://stackoverflow.com/a/30787112/4539192).

0
On

Firstly, thanks to Serghei for his time in helping work through this.

To clarify, both my potential presented controllers were set to Full Screen presentation style in the storyboard, however one was being set to Custom via a piece of pasted code dealing with the presentation. I can't find the error with the other.

However, if I force a presentation style of Full Screen as part of the presenting process then all is ok.

Hopefully my frustrating afternoon can help to save someone else's - always try to understand the implications and processes involved in pasted snippets.

5
On

EDIT: This is in Swift 3, you can adjust your method accordingly if you're using an older version of Swift

If you won't be able to figure out why viewDidAppear and viewDidDisappear are not called, here's a workaround

protocol MyControllerDelegate {
    func myControllerWillDismiss()
}

class MyController: UIViewController {
    var delegate: MyControllerDelegate?

// your controller logic here

    func dismiss() { // call this method when you want to dismiss your view controller

        // inform delegate on dismiss that you're about to dismiss
        delegate?.myControllerWillDismiss()
        dismiss(animated: true, completion: nil)
    }
}

class PresentingController: UIViewController, MyControllerDelegate  {
    func functionInWhichYouPresentMyController() {
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let navController = storyboard.instantiateViewController(withIdentifier: "NavController") as! UINavigationController
        let thisController = navController.viewControllers[0] as! MyController
        thisController.delegate = self // assign self as delegate
        present(navController, animated: true, completion: {
            // place your code that you want executed when it disappears here
        })
    }

    func myControllerWillDismiss() {
        // this method will be called now when MyController will dismiss
        // place your code that you want executed when it re-appears here
    }
}