无需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
相关产品推荐
相关产品推荐

