如何在RootVC嵌套ContainerVC时用闭包实现ViewController间数据传递?
No problem at all! Since we've got a hierarchy here (RootVC → PageViewController → SubContainerVC), we just need to create a closure chain to pass the update action through each layer. Let's break this down step by step with code changes:
1. Add an Update Method & Pass Closure from RootVC
First, let's add a dedicated method in RootVC to handle incrementing the count and updating the label. We'll also pass a reference to this method (via closure) to the PageViewController when we initialize it:
class RootVC: UIViewController { // ... existing code ... func incrementCount() { tappedCount += 1 label.text = "\(tappedCount)" } override func viewDidLoad() { super.viewDidLoad() // ... existing code ... // Modify PageViewController initialization to pass our closure let pageController = PageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal) // Use [weak self] to avoid retain cycles pageController.buttonTapHandler = { [weak self] in self?.incrementCount() } addChild(pageController) // ... rest of your existing setup code ... } }
2. Forward the Closure in PageViewController
Next, add a closure property to PageViewController that holds the action from RootVC, then pass this closure directly to the SubContainerVC when creating it:
class PageViewController: UIPageViewController { // Add this closure property to receive the action from RootVC var buttonTapHandler: (() -> Void)? lazy var subViewControllers:[UIViewController] = { let subVC = SubContainerVC() // Forward the closure to SubContainerVC subVC.callback = self.buttonTapHandler return [subVC] }() // ... existing init and viewDidLoad code ... }
3. Trigger the Closure in SubContainerVC
Finally, execute the closure when the button is tapped in SubContainerVC—this will fire the action we passed all the way from RootVC:
class SubContainerVC: UIViewController { // ... existing code ... @objc func buttonPressed(_ sender: UIButton) { print("Hello") // Call the closure to trigger the count update in RootVC callback?() } // ... existing viewDidLoad code ... }
How This Works
- When
RootVCsets upPageViewController, it passes a closure that calls its ownincrementCount()method. PageViewControllerforwards this closure toSubContainerVCduring initialization.- When the button in
SubContainerVCis tapped, it runs the closure, which triggersRootVC's count update logic—updating both thetappedCountvariable and the on-screen label.
This approach keeps your view controllers decoupled (each only knows about the closure it needs, not the entire parent hierarchy) and avoids memory leaks thanks to the [weak self] capture list.
内容的提问来源于stack exchange,提问作者swiftnjava

