Swift 4:dismiss过渡视图控制器后正确调用viewWillAppear的方法
Hey there! Let's break down why your current code is crashing and walk through the correct ways to handle this.
What's Wrong With Your Current Approach?
When you call ViewController1().viewWillAppear(true), you're creating a brand new instance of ViewController1—not the original one that presented ViewController2. This fresh instance hasn't been properly initialized, loaded, or connected to your view hierarchy, which is why you're hitting a null value crash.
Correct Solutions
1. Use presentingViewController to Access the Original ViewController1
Every presented view controller has a presentingViewController property that points to the VC that presented it. You can safely cast this to your ViewController1 type and call viewWillAppear directly:
Option A: Call in the dismiss completion handler
// Inside ViewController2, when you want to dismiss self.dismiss(animated: true) { [weak self] in // Safely cast the presenting VC to ViewController1 guard let viewController1 = self?.presentingViewController as? ViewController1 else { return } viewController1.viewWillAppear(true) }
Option B: Call in viewDidDisappear
If you prefer to trigger it when ViewController2 fully disappears:
override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) guard let viewController1 = presentingViewController as? ViewController1 else { return } viewController1.viewWillAppear(true) }
2. Use a Closure Callback (Cleaner, More Flexible)
This approach lets you pass a custom action from ViewController1 to ViewController2, so you don't have to rely on casting the presenting VC:
Step 1: Add a closure property to ViewController2
class ViewController2: UIViewController { // Define a closure to hold the action to run on dismiss var onDismiss: (() -> Void)? // ... rest of your code }
Step 2: Set the closure in ViewController1's segue preparation
class ViewController1: UIViewController { override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if let viewController2 = segue.destination as? ViewController2 { // Pass the action we want to run when ViewController2 is dismissed viewController2.onDismiss = { [weak self] in self?.viewWillAppear(true) } } } // ... rest of your code }
Step 3: Trigger the closure when dismissing ViewController2
// Inside ViewController2 self.dismiss(animated: true) { [weak self] in // Execute the closure passed from ViewController1 self?.onDismiss?() }
Important Note: Avoid Memory Leaks
Always use [weak self] in closures to prevent strong reference cycles—this ensures both view controllers can be deallocated properly when they're no longer needed.
Bonus: Why Isn't viewWillAppear Triggered Automatically?
For overContext transitions, ViewController1's view stays visible behind ViewController2, so the system doesn't automatically call viewWillAppear when you dismiss. That's why you need to trigger it manually using one of the methods above.
内容的提问来源于stack exchange,提问作者husharoonie

