视图控制器之间的数据传递

How To: Pass Data Between View Controllers In Swift

  • 多个消息传递:使用代理

    使用闭包会导致代码臃肿。

  • 委托者要调用多个代理对象:使用闭包

    因为委托者中的代理对象保存的是个引用,若设置多个代理对象,那么只有最后一个引用的设置会生效。

  • 单例不要用代理

1.使用闭包

img

Passing Data Back With a Closure

在B中:定义一个闭包属性,并且将数据传给闭包的参数

1
2
3
4
5
6
class BViewController: UIViewController{
var selfClassName: ((String) -> Void)? //闭包存储属性
@objc private func buttonCDidPress(sender: UIButton) {
self.selfClassName?("\(LessonIntroduceViewController.self)") //给闭包传参数
}
}

在A中:

1
2
3
4
5
6
7
class AViewController: UIViewController{
let bViewController = BViewController()
//给B中的闭包属性赋值,来处理接收到的数据
bViewController.selfClassName = { (str: String) -> Void in
self.view.makeToast("\(str)")
}
}

2.使用代理

img

协议

1
2
3
protocol PizzaDelegate: AnyObject {
func onPizzaReady(type: String)
}

在A中,实现代理函数

1
2
3
4
5
class AViewController: PizzaDelegate {
func onPizzaReady(type: String) { //用来处理B传来的数据
print("Pizza ready. The best pizza of all pizzas is... \(type)")
}
}

在B中,将数据传给代理函数的参数

1
2
3
4
5
6
7
class BViewController {
weak var delegate:PizzaDelegate?

@IBAction func onButtonTap() {
delegate?.onPizzaReady(type: "Pizza di Mama") //可将数据传给onPizzaReady的参数
}
}

3.使用NotificationCenter

⚠️:若是接收通知之后的处理有UI更新操作,一定要事先将线程调到主线程。

img

在A中,定义通知名称作为类属性,在界面加载时添加观察,实现观察响应函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class AViewController: UIViewController {
//类属性
static let notificationName = Notification.Name("myNotificationName")
//添加观察
override func viewDidLoad() {
NotificationCenter.default.addObserver(
self, //观察的对象
selector: #selector(onNotification(notification:)), //通知响应函数
name: AViewController.notificationName, //通知名称
object: nil //可以指定从特定的对象接收通知
)
}
//响应函数
override func viewWillDiresappear(_ animated: Bool) {
NotificationCenter.default.removeObserver(self)
}
}
extension AViewController {
//@objc要有,因为NSNotificationCenter是Objective-C代码
@objc func onNotification(notification: Notification) {
print(notification.userInfo)
}
}

在B中,发出通知

1
2
3
4
5
6
7
8
9
class BViewController {
@IBAction func onButtonTap() {
NotificationCenter.default.post(
name: AViewController.notificationName,
object: nil, //通知的发出者
userInfo:["data": 42, "isImportant": true]
)
}
}

4.使用属性和函数

在B中,声明一个A的引用,然后调用A的函数

1
2
3
4
5
6
7
class BViewController: UIViewController {
var aViewController:AViewController?

@IBAction func onButtonTap() {
aViewController?.onUserAction(data: "The quick brown fox jumps over the lazy dog")
}
}

在A中,生成B的对象时,B对象中的指向A的引用赋值为swlf

1
2
3
4
5
6
7
8
9
10
class AViewController: UIViewController {
override func viewDidLoad() {
let vc = BViewController()
vc.aViewController = self
}

func onUserAction(data: String) {
print("Data received: \(data)")
}
}
0%