Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I refresh ViewController after dismiss method is called

Tags:

xcode

swift

For example, I have two viewControllers named A and B. I move to "B view controller" after present method is called. I set some values through UserDefaults.stnadard on "B viewController", and I come back to "A view controller" after dismiss method is called. "A viewController" have to show modified values, but it doesn't show the modified ones. I tried calling viewDidAppear() method on "A viewController", but it didn't work. I tried calling viewDidLoad() method, and it worked well, but I heard that it's not a good way to call the method directly. System can only call it. So, I don't want to call it myself. How should I refresh "A view controller"?

like image 717
lulzo Avatar asked Oct 15 '25 07:10

lulzo


2 Answers

From iOS 13.0 and above, Apple has changed the way viewControllers are presented by default. So, viewWillAppear in ViewControllerA will not be called after dimissing ViewControllerB.

One way for making sure the viewWillAppear method will be called after dismissing ViewControllerB is presenting the viewController setting modalPresentationStyle to fullScreen as:

let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(identifier: "ViewControllerB") as! ViewControllerB
vc.modalPresentationStyle = .fullScreen
self.present(vc, animated: true, completion: nil)

Sample Code:

ViewControllerA.swift

class ViewControllerA: UIViewController {

    private var username: String? {
        UserDefaults.standard.string(forKey: "USERNAME")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        print(username) //set this to desired view
    }

    @IBAction func goToViewControllerB(_ sender: UIButton) {
        let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(identifier: "ViewControllerB") as! ViewControllerB
        vc.modalPresentationStyle = .fullScreen
        self.present(vc, animated: true, completion: nil)
    }
}

ViewControllerB.swift

class ViewControllerB: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        UserDefaults.standard.set("John", forKey: "USERNAME")
    }

    @IBAction func dismiss(_ sender: Any) {
        self.dismiss(animated: true, completion: nil)
    }
}

If you don't want to change the modalPresentationStyle to fullScreen then you can use closures for passing data to ViewControllerA when you're dismissing ViewControllerB.

like image 152
Nabin Shrestha Avatar answered Oct 17 '25 21:10

Nabin Shrestha


I think NotificationCenter or prototype would help get this done.

NotificationCenter example

class ViewControllerA: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(testFunc), name: NSNotification.Name(rawValue:  "PeformAfterPresenting"), object: nil)

    }

    @objc func testFunc() {
      //TODO: your task
    }
}

class ViewControllerB: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()
}

@IBAction func dismiss(_ sender: Any) {

    NotificationCenter.default.post(name: "PeformAfterPresenting"), object: nil, userInfo: dataDict)

        self.dismiss(animated: true, completion: nil)
    }
}
like image 25
Niki Avatar answered Oct 17 '25 21:10

Niki



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!