Swift:如何在两个ViewController间推送通知并传递函数执行结果?
嘿,我来帮你搞定这个跨ViewController的通知调用问题!在Swift开发里,这种场景其实挺常见的,我给你两种靠谱的解决方案,你可以根据自己的需求选:
方案一:用NotificationCenter实现触发调用(适合单向触发)
这是最经典的跨组件通知方式,适合只需要触发第一个VC的函数,不需要返回值给第二个VC的场景(当然第一个VC里可以自己打印结果)。
1. 在第一个ViewController中注册通知
首先我们要给第一个VC注册自定义通知,同时记得在销毁时移除观察者,避免内存泄漏:
class FirstViewController: UIViewController { // 定义全局唯一的通知名称,建议用extension统一管理,避免拼写错 static let callFirstVCFunctionNotification = Notification.Name("CallFirstVCFunction") override func viewDidLoad() { super.viewDidLoad() // 注册通知,绑定要执行的指定函数 NotificationCenter.default.addObserver( self, selector: #selector(runSpecifiedFunction), name: FirstViewController.callFirstVCFunctionNotification, object: nil ) } deinit { // 页面销毁时移除观察者,防止内存泄漏 NotificationCenter.default.removeObserver(self) } // 你需要被调用的指定函数,要加@objc让NotificationCenter能识别 @objc func runSpecifiedFunction() { let executionResult = "第一个VC的指定函数执行完成!" print(executionResult) // 如果需要把结果传给第二个VC,可以通过通知的userInfo传递,后面会说 } }
2. 在第二个ViewController中发送通知
当你需要触发第一个VC的函数时,直接发送我们定义的通知就行:
class SecondViewController: UIViewController { // 比如在按钮点击事件里触发 @IBAction func triggerFirstVCFunction(_ sender: UIButton) { NotificationCenter.default.post( name: FirstViewController.callFirstVCFunctionNotification, object: nil ) } }
如果需要第一个VC把执行结果回传给第二个VC,那可以修改通知的userInfo:
// 第一个VC的函数里修改 @objc func runSpecifiedFunction() { let executionResult = "第一个VC的指定函数执行完成!" print(executionResult) // 先新增一个结果通知的名称 static let resultReturnNotification = Notification.Name("FirstVCFunctionResult") // 把结果通过userInfo传递回去 NotificationCenter.default.post( name: FirstViewController.resultReturnNotification, object: nil, userInfo: ["result": executionResult] ) } // 第二个VC里注册这个结果通知 override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver( self, selector: #selector(receiveFunctionResult(_:)), name: FirstViewController.resultReturnNotification, object: nil ) } @objc func receiveFunctionResult(_ notification: Notification) { if let result = notification.userInfo?["result"] as? String { print("第二个VC收到的执行结果:\(result)") } }
方案二:用闭包实现(适合需要双向传递数据的场景)
如果你的需求是第二个VC要直接拿到第一个VC函数的执行结果,用闭包会比通知更直接,因为通知是单向通信,闭包可以直接回调获取值。
1. 在第二个ViewController中定义闭包属性
class SecondViewController: UIViewController { // 定义闭包,用来触发第一个VC的函数并接收返回值 var getFirstVCFunctionResult: (() -> String?)? @IBAction func triggerFirstVCFunction(_ sender: UIButton) { // 调用闭包,获取第一个VC函数的结果并打印 if let result = getFirstVCFunctionResult?() { print("第二个VC收到的执行结果:\(result)") } } }
2. 在第一个ViewController跳转时绑定闭包
当你从第一个VC跳转到第二个VC时,把闭包指向你要执行的指定函数:
class FirstViewController: UIViewController { // 跳转逻辑,比如按钮点击或者其他触发时机 func goToSecondVC() { let secondVC = SecondViewController() // 绑定闭包,注意用[weak self]避免循环引用 secondVC.getFirstVCFunctionResult = { [weak self] in guard let self = self else { return nil } return self.runSpecifiedFunction() } navigationController?.pushViewController(secondVC, animated: true) } // 你的指定函数,不需要加@objc了 func runSpecifiedFunction() -> String { let executionResult = "第一个VC的指定函数执行完成!" print(executionResult) return executionResult } }
关键注意点
- 用
NotificationCenter时,一定要在deinit里移除观察者,不然会导致内存泄漏,VC无法被释放。 - 用闭包时,必须用
[weak self]或者[unowned self]避免循环引用,尤其是两个VC通过导航栈关联的时候,很容易出现循环引用的问题。 - 通知名称最好用
extension Notification.Name来统一管理,比如:
extension Notification.Name { static let callFirstVCFunction = Notification.Name("CallFirstVCFunction") static let firstVCFunctionResult = Notification.Name("FirstVCFunctionResult") }
这样可以避免拼写错误,代码也更整洁。
两种方案都能实现你要的效果,如果你只需要触发第一个VC的函数并让它自己打印结果,方案一足够;如果第二个VC需要拿到结果,方案二更直接。
内容的提问来源于stack exchange,提问作者Biba
相关产品推荐
相关产品推荐

