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

无需Segue,从容器视图向主视图控制器传递trackNumber值的方案

如何在容器视图的SelectSoundVC中向MainVC传递trackNumber值(不使用Segue)

嘿,这个场景我太熟悉啦!既然SelectSoundVC是MainVC的容器子控制器,咱们完全不用Segue就能轻松实现值传递,给你分享几个常用且靠谱的方法:

方法一:直接获取父控制器引用(最简单直接)

因为SelectSoundVC是MainVC的子控制器,所以可以直接通过parent属性拿到MainVC的实例,然后直接给recivedTrackNumber赋值。修改你的SelectSoundVC代码就行:

import UIKit
class SelectSoundVC: UIViewController {
    var trackNumber: Int!
    @IBAction func winterSoundBut(_ sender: UIButton) {
        trackNumber = 1
        // 强转父控制器为MainVC,然后赋值
        if let mainVC = self.parent as? MainVC {
            mainVC.recivedTrackNumber = trackNumber
        }
    }
}

这个方法的优点是零额外配置,代码少,适合这种明确的父子控制器关系场景,只要确保你的parent确实是MainVC就行。

方法二:使用闭包(解耦性更强,推荐)

如果想让两个控制器的耦合度更低(比如以后可能把SelectSoundVC放到其他控制器里),闭包是更好的选择。

首先在SelectSoundVC里定义一个闭包属性:

import UIKit
class SelectSoundVC: UIViewController {
    var trackNumber: Int!
    // 定义闭包,用来传递选中的trackNumber
    var onTrackNumberSelected: ((Int) -> Void)?
    
    @IBAction func winterSoundBut(_ sender: UIButton) {
        trackNumber = 1
        // 触发闭包,把值传出去
        onTrackNumberSelected?(trackNumber)
    }
}

然后在MainVC里,当容器子控制器加载完成后,设置这个闭包:

class MainVC: UIViewController {
    var recivedTrackNumber: Int!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 从子控制器列表里找到SelectSoundVC
        if let selectSoundVC = self.children.first as? SelectSoundVC {
            // 设置闭包,接收传过来的值
            selectSoundVC.onTrackNumberSelected = { [weak self] selectedTrack in
                self?.recivedTrackNumber = selectedTrack
            }
        }
    }
}

用闭包的好处是,SelectSoundVC完全不需要知道MainVC的存在,只负责在值变化时触发闭包,解耦性拉满,以后复用SelectSoundVC也更方便。

方法三:使用通知中心(适合复杂跨层级场景)

如果你的项目有更复杂的传值需求(比如跨多个控制器层级),通知中心也能搞定,但对于这个父子容器的场景来说有点“大材小用”,不过也给你列出来参考:

先在MainVC里监听自定义通知:

class MainVC: UIViewController {
    var recivedTrackNumber: Int!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 注册通知监听
        NotificationCenter.default.addObserver(self, selector: #selector(updateTrackNumber(_:)), name: NSNotification.Name("TrackNumberUpdated"), object: nil)
    }
    
    @objc private func updateTrackNumber(_ notification: Notification) {
        // 从通知的userInfo里取出值
        if let trackNum = notification.userInfo?["trackNumber"] as? Int {
            recivedTrackNumber = trackNum
        }
    }
    
    deinit {
        // 记得移除监听,避免内存泄漏
        NotificationCenter.default.removeObserver(self)
    }
}

然后在SelectSoundVC的按钮点击事件里发送通知:

@IBAction func winterSoundBut(_ sender: UIButton) {
    trackNumber = 1
    // 发送通知,把值放在userInfo里
    NotificationCenter.default.post(name: NSNotification.Name("TrackNumberUpdated"), object: nil, userInfo: ["trackNumber": trackNumber])
}

这个方法的优点是可以跨任意层级传递值,但缺点是需要手动管理监听的注册和移除,而且代码量相对多一些,所以如果只是父子容器的场景,优先选前两种方法。

内容的提问来源于stack exchange,提问作者Ula

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:05:49