iOS开发:如何从FourthController跳转回嵌入的初始页面?
Got it, let's break down how to add that restart functionality cleanly, fitting with your existing parent-child controller architecture. The best approach here is using a delegate pattern—it keeps your code decoupled and aligns with how your app already manages controller swaps.
Step 1: Add Delegate Protocol to FourthController
First, define a protocol in FourthController to communicate the restart action back to the parent ViewController, then add a button tap handler:
import UIKit // Define a delegate protocol for restart events protocol FourthControllerDelegate: AnyObject { func didRequestRestart() } class FourthController: UIViewController { var survey: Survey! // Weak reference to avoid retain cycles weak var delegate: FourthControllerDelegate? // Connect this IBAction to your restart button in Storyboard @IBAction func restartTapped(_ sender: UIButton) { // Notify the parent controller to handle restart delegate?.didRequestRestart() } // Your existing FourthController code... }
Step 2: Make ViewController Conform to the Delegate
Update your main ViewController to adopt the delegate protocol and implement the restart logic—reusing your existing moveAndSizeChildControllers method to keep consistency:
extension ViewController: FourthControllerDelegate { func didRequestRestart() { // Instantiate the FirstController guard let firstController = storyboard?.instantiateViewController(withIdentifier: "FirstController") as? FirstController else { return } // Reset survey data if needed (use self.survey if you want to keep existing data) firstController.survey = Survey() // Swap the current controller with FirstController if let currentController = currentController { moveAndSizeChildControllers(fromController: currentController, toController: firstController) // Reset page index to initial state pageIndex = 1 setButtonAndProgressLabel() } } }
Step 3: Assign the Delegate When Navigating to FourthController
In your ViewController's nextTapped method, set the delegate for FourthController when you instantiate it:
case 3: let nextController = storyboard?.instantiateViewController(withIdentifier: "FourthController") if let fromController = currentController, let toController = nextController as? FourthController { toController.survey = survey // Set the delegate to self so FourthController can notify us toController.delegate = self moveAndSizeChildControllers(fromController: fromController, toController: toController) pageIndex += 1 setButtonAndProgressLabel() }
Why This Works
- Low Coupling:
FourthControllerdoesn't need to know anything aboutViewController's internal logic—it just signals that a restart is requested. - Consistency: Reuses your existing controller swap method, so the animation and state management stays identical to your forward/back navigation.
- Memory Safe: Using a
weakdelegate reference prevents retain cycles.
Alternative: Notification Center (Less Recommended)
If you prefer a looser connection, you could use NotificationCenter, but this is overkill for a direct parent-child relationship:
// In FourthController's restartTapped NotificationCenter.default.post(name: NSNotification.Name("RestartSurvey"), object: nil) // In ViewController's viewDidLoad NotificationCenter.default.addObserver(self, selector: #selector(handleRestart), name: NSNotification.Name("RestartSurvey"), object: nil) // Add handler in ViewController @objc func handleRestart() { // Same restart logic as the delegate method } // Don't forget to remove observer in deinit deinit { NotificationCenter.default.removeObserver(self) }
内容的提问来源于stack exchange,提问作者Kunduri Raj

