You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在RootVC嵌套ContainerVC时用闭包实现ViewController间数据传递?

Solution: Closure-Based Data Passing Across Indirectly Linked View Controllers

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 RootVC sets up PageViewController, it passes a closure that calls its own incrementCount() method.
  • PageViewController forwards this closure to SubContainerVC during initialization.
  • When the button in SubContainerVC is tapped, it runs the closure, which triggers RootVC's count update logic—updating both the tappedCount variable 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 10:48:11