ViewController 之间传递信息
iOS 开发中,不同的 ViewController 之间传递信息的方式有好几种。这里介绍常见的三种方式,使用自带的 prepare 方式、使用委托模式、使用回调函数与闭包结合的方式。
主 Controller A 向副 Controller B 传递
首先,自定义的主 ViewController A 是继承了 UIViewController 的
class ViewController: UIViewController{
}
接着,重写 Controller A 的 prepare 方法,这里的判断 segue 连线的目的地是否为 TaskViewController 从而进一步拿到 TaskViewController(ViewController B) 实例向它传递信息。
// The pre entry to the TaskCreateController
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let father = sender as? ViewController {
print(father.nextNewTaskType)
}
if segue.destination is TaskCreateController {
if let creator = segue.destination as? TaskCreateController {
creator.taskType = self.nextNewTaskType // 向 Controller B 的 taskType 传递信息。
}
}
副 Controller B 向主 Controller A 传递
方法一:使用委托模式(常用)
定义一个委托接口 C
protocol MessageTaskCreated {
func taskCreated(_ task: Task)
}
Controller B 拥有一个协议成员,在需要传递信息的时候,调用协议的方法传递。这里我们调用 taskCreated(_ task: Task)
传递了一个 task。
// Controller B 中
var messageTaskCreated: MessageTaskCreated? = nil // delegation
@IBAction func btnConfirm(_ sender: Any) {
var task = Task()
self.dismiss(animated: true)
if let delegate = messageTaskCreated {
delegate.taskCreated(task)
}
}
Controller A 遵守协议 C, 在跳转到 Controller B 的时候向 B 注入自己(Controller 实例)的引用。因为自己遵守了协议 MessageTaskCreated
所以可以正确地注入, 并且需要实现方法 taskCreated
.
// 遵守协议 MessageTaskCreated
class ViewController: UIViewController, MessageTaskCreated {
}
// Controller A 中
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.destination is TaskCreateController {
if let creator = segue.destination as? TaskCreateController {
creator.messageTaskCreated = self // 注入自己的引用,让 Controller B(creator) 能调用 A 的方法。
}
}
}
// 实现来自协议的方法,这个方法将会被 Controller B 调用
func taskCreated(_ task: Task) {
Home.tasks.append(task)
tasksView.reloadData()
}
方法二:使用回调函数加闭包(最为简便)
对于 Controller A,这种方法比方法一更加安全一些,因为没有传递主 Controller A 的引用,只是调用来 self.taskView.reloadData()
, 关于self 的其它部分不可见。
Controller B 设定一个回调函数,在需要传递信息的地方调用它。
var callBack: ((Task) -> Void)? // 回调函数
@IBAction func btnConfirm(_ sender: Any) {
var task = Task()
self.dismiss(animated: true)
callBack?(task) // 调用
}
Controller A 在 prepare 函数中,给 Controller B 的实例(creator)传递一个闭包。
// The pre entry to the TaskCreateController
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.destination is TaskCreateController {
if let creator = segue.destination as? TaskCreateController {
// 传递闭包给回调函数
creator.callBack = { task in
Home.tasks.append(task)
self.tasksView.reloadData()
}
}
}
}