简体   繁体   中英

Swift viewWillAppear not being called after dismissing view controller

I am presenting a view controller from a view controller called HomeController like so:

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

let navigationController: UINavigationController = UINavigationController(rootViewController: viewController)

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

In the presented view controller LoginController at some point gets dismissed:

self.dismiss(animated: true, completion: nil)

But when it comes back to HomeController it is not calling viewWillAppear, I really need to check on condition on HomeController when it comes back to it, So how can I call viewWillAppear when LoginController dismisses the view?

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)

If presented viewController is half screen then you will have to Call the viewWillAppear of presenting viewController manually in side presented view controller's viewWillDisappear. Add following code to your Presented view controller.

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    presentingViewController?.viewWillDisappear(true)
}    

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    presentingViewController?.viewWillAppear(true)
}

Note: you must have to call 'presentingViewController?.viewWillDisappear(true)' to get your Presenting view controllers viewWillAppear execute everytime.

In iOS 13 , if you are presenting a view controller and when you are coming back viewWillAppear doesn't get called . I have changed it from present to push view controller and methods are getting called now .

Changing presentation style to .fullScreen works but changes the appearance of the presented view Controller. If u want to avoid that u can override the viewWillDisappear method in the presented viewcontroller and inside it add presentingViewController?.viewWillAppear(true) .

Example:

 class ViewControllerA: UIViewController {
 
      override func viewDidLoad() {
          super.viewDidLoad()
          
          //put the presenting action wherever you want

          let vc = ViewControllerB()
          navigationController.present(vc, animated: true)
      }

      override func viewWillAppear(_ animated: Bool) {
           super.viewWillAppear(animated) 
           //refresh Whatever 
      }
 }

 class ViewControllerB: UIViewController {
 
      override func viewDidLoad() {
          super.viewDidLoad()
      }

      override func viewWillDisappear(_ animated: Bool) {
          super.viewWillDisappear(animated)

          //this will call the viewWillAppear method from ViewControllerA  

          presentingViewController?.viewWillAppear(true)
      }
 }

Swift 5. Work for me. Maybe all forget about delegate.

First Controller

let calendarVC = CalendarVC()
calendarVC.delegate = self
calendarVC.modalTransitionStyle = .coverVertical
present(calendarVC, animated: true, completion: nil)

Present controller

Add Delegate........

override func viewWillDisappear(_ animated: Bool) {
  super.viewWillDisappear(animated)
        delegate?.closeState()
 }

Work when swipe and dismiss button. Have a good day )

None of these solutions seemed satisfactory, and indeed the solutions that suggested calling presentingViewController?.viewWillAppear(true) actually break animations in navigations controllers and throws warnings from UIKit in the console.

The correct way is to use the built in methods in UIKit, as suggested by the warnings! These will call all the respective methods viewWill / DidAppear in the presenting class.

Note I have an if statement checking if the modelPresentationStyle is equal to pageSheet as this is the value that recent releases of iOS set the default presentation style to. We do not want to interfere with other presentation styles as they may already call viewWill / DidAppear and it should not be called twice.

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    // view lifecycle events are not passed down to the presentingViewController if in pageSheet style (and maybe others)
    if modalPresentationStyle == .pageSheet {
        presentingViewController?.beginAppearanceTransition(false, animated: animated)
    }
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    // view lifecycle events are not passed down to the presentingViewController if in pageSheet style (and maybe others)
    if modalPresentationStyle == .pageSheet {
        presentingViewController?.endAppearanceTransition()
    }
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    // view lifecycle events are not passed down to the presentingViewController if in pageSheet style (and maybe others)
    if modalPresentationStyle == .pageSheet {
        presentingViewController?.beginAppearanceTransition(true, animated: animated)
    }
}

override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)

    // view lifecycle events are not passed down to the presentingViewController if in pageSheet style (and maybe others)
    if modalPresentationStyle == .pageSheet {
        presentingViewController?.endAppearanceTransition()
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM