Cocoa Swift 用protocol与delegate在两个ViewController间回传数据失败怎么办
问题根因
- 从FirstViewController跳转至SecondViewController时,未给新创建的SecondViewController实例的
delegate属性赋值,代理默认值为nil,后续回调逻辑无法触发 - SecondViewController点击返回按钮时,先执行了页面跳转再调用代理方法,跳转后当前Second实例可能被释放,weak修饰的delegate会自动置空,同时你重新实例化了一个全新的FirstViewController,和之前跳转前的First实例不是同一个对象,就算回调触发也不会修改原有页面的UI
修正代码
FirstViewController.swift
// FirstViewController.swift import Cocoa class FirstViewController: NSViewController, DataEnteredDelegate { @IBOutlet weak var buttonPasswordState: NSView! @IBOutlet weak var label: NSTextField! override func viewDidLoad() { super.viewDidLoad() } @IBAction func buttonPasswordState(_ sender: Any) { guard let controller = self.storyboard?.instantiateController(withIdentifier: "SecondViewController") as? SecondViewController else { return } // 给SecondViewController的代理赋值为当前First实例 controller.delegate = self self.view.window?.contentViewController = controller } func userDidEnterInformation(info: String) { label.stringValue = info // 可添加日志确认回调触发 print("接收到回传数据: \(info)") } }
SecondViewController.swift
// SecondViewController.swift import Cocoa protocol DataEnteredDelegate: class { func userDidEnterInformation(info: String) } class SecondViewController: NSViewController { @IBOutlet weak var buttonContinue: NSButton! weak var delegate: DataEnteredDelegate? = nil @IBOutlet weak var textField: NSTextField! override func viewDidLoad() { super.viewDidLoad() } @IBAction func buttonContinue(_ sender: Any) { // 先执行代理回调传递数据,再执行页面跳转 delegate?.userDidEnterInformation(info: textField.stringValue) // 不需要重新实例化FirstViewController,直接切换回原有页面即可,若为模态弹出场景可直接调用dismiss guard let controller = self.storyboard?.instantiateController(withIdentifier: "FirstViewController") as? FirstViewController else { return } self.view.window?.contentViewController = controller } }
调试提示
可在代理调用位置和代理实现位置增加打印日志,若调用代理前打印delegate值为nil,说明跳转前的代理赋值逻辑未生效,可检查Storyboard中ViewController的Identifier是否正确配置。
内容的提问来源于stack exchange,提问作者iosSwift
相关产品推荐
相关产品推荐

