Swift中从secondVC返回时向ViewController传递标签文本的实现方法
解决返回时secondVC向ViewController传递数据的问题
需求是:点击导航栏返回按钮时,把secondVC里resultLabel的文本传给ViewController的nameLabel。你之前用prepare(for:sender:)没用是因为这个方法是正向跳转(从VC到secondVC)时执行的,这时候secondVC的resultLabel还没有用户输入的内容,反向传值得在返回动作触发时处理。
下面给两种常用的实现方式:
方法一:代理模式
代理是iOS反向传值的经典方案,步骤如下:
在secondVC中定义代理协议
给secondVC添加代理协议,规定数据传递的方法:import UIKit // 定义代理协议 protocol SecondVCDelegate: AnyObject { func secondVC(_ vc: secondVC, didReturnWithText text: String?) } class secondVC: UIViewController { @IBOutlet weak var nameField: UITextField! @IBOutlet weak var resultLabel: UILabel! // 代理属性,用weak避免循环引用 weak var delegate: SecondVCDelegate? override func viewDidLoad() { super.viewDidLoad() } @IBAction func saveClicked(_ sender: Any) { resultLabel.text = nameField.text } // 监听返回动作,判断当前VC是否被弹出导航栈 override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) if isMovingFromParent { delegate?.secondVC(self, didReturnWithText: resultLabel.text) } } }让ViewController遵守代理协议并实现方法
修改ViewController代码,在跳转时设置代理,实现代理方法更新标签:import UIKit // 遵守代理协议 class ViewController: UIViewController, SecondVCDelegate { @IBOutlet weak var nameLabel: UILabel! override func viewDidLoad() { super.viewDidLoad() } @IBAction func goVC2(_ sender: Any) { performSegue(withIdentifier: "toVC2", sender: nil) } // 正向跳转时设置代理 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "toVC2" { let vc = segue.destination as! secondVC vc.delegate = self } } // 实现代理方法,接收数据更新标签 func secondVC(_ vc: secondVC, didReturnWithText text: String?) { nameLabel.text = text } }
方法二:闭包回调
闭包是更简洁的反向传值方式,代码量更少:
在secondVC中添加闭包属性
定义闭包用于传递数据,在返回时调用:import UIKit class secondVC: UIViewController { @IBOutlet weak var nameField: UITextField! @IBOutlet weak var resultLabel: UILabel! // 定义可选闭包,避免未赋值导致崩溃 var onBack: ((String?) -> Void)? override func viewDidLoad() { super.viewDidLoad() } @IBAction func saveClicked(_ sender: Any) { resultLabel.text = nameField.text } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) if isMovingFromParent { // 调用闭包传递数据 onBack?(resultLabel.text) } } }在ViewController中设置闭包
在跳转时给secondVC的闭包赋值,接收数据更新标签:import UIKit class ViewController: UIViewController { @IBOutlet weak var nameLabel: UILabel! override func viewDidLoad() { super.viewDidLoad() } @IBAction func goVC2(_ sender: Any) { performSegue(withIdentifier: "toVC2", sender: nil) } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "toVC2" { let vc = segue.destination as! secondVC // 设置闭包,用weak self避免循环引用 vc.onBack = { [weak self] text in self?.nameLabel.text = text } } } }
注意点
- 不管用代理还是闭包,都要用
weak引用ViewController,避免循环引用导致内存泄漏。 isMovingFromParent用来判断当前VC是否被弹出导航栈,确保只有点击返回按钮时才传递数据,排除其他页面消失场景(比如push新VC)。
内容的提问来源于stack exchange,提问作者ShakyAardvark
相关产品推荐
相关产品推荐

