重复添加相同观察者
我们先来看看日常开发中我们对 NSNotification 的正常用法,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| let TestNotification = NSNotification.Name.init("com.papa.test")
class Test {
init() { NotificationCenter.default.addObserver(self, selector: #selector(Test.test(notification:)), name: TestNotification, object: nil) }
deinit { NotificationCenter.default.removeObserver(self) }
@objc func test(notification: Notification) { print("Test") } }
|
但是如果我们在刚才代码中的 init
方法里面对同一个通知多次添加同一个观察者的话,会发生什么?
1 2 3 4 5 6 7
| init() { NotificationCenter.default.addObserver(self, selector: #selector(Test.test(notification:)), name: TestNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(Test.test(notification:)), name: TestNotification, object: nil) }
NotificationCenter.default.post(name: TestNotification, object: nil)
|
答案是会输出:
所以我们要尽量避免重复添加观察者,因为这有可能会造成一些未知现象的发生。
通知中的线程问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| let ThreadNotification = NSNotification.Name.init("com.papa.thread")
class Test {
init() { print("Add Observer: \(Thread.current)") NotificationCenter.default.addObserver(self, selector: #selector(Test.test(notification:)), name: ThreadNotification, object: nil) }
deinit { NotificationCenter.default.removeObserver(self) }
@objc func test(notification: Notification) { print("Receive: \(Thread.current)") } }
DispatchQueue.init(label: "com.ps.test.queue").async { print("Post: \(Thread.current)") NotificationCenter.default.post(name: ThreadNotification, object: nil) }
|
我们来看看观察者是在什么线程上接受到通知的:
1 2 3
| Add Observer: <NSThread: 0x60000147d1c0>{number = 1, name = main} Post: <NSThread: 0x600001462640>{number = 3, name = (null)} Receive: <NSThread: 0x600001462640>{number = 3, name = (null)}
|
虽然我们是在主线程中去添加观察者,但是因为我们是在其他线程中去发送通知的,所以最后我们也是在其他线程中接收到通知的。
通知中的阻塞问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| let SleepNotification = NSNotification.Name.init("com.papa.sleep")
class Test {
init() { NotificationCenter.default.addObserver(self, selector: #selector(Test.test(notification:)), name: SleepNotification, object: nil) }
deinit { NotificationCenter.default.removeObserver(self) }
@objc func test(notification: Notification) { sleep(3) } }
let start = Date() NotificationCenter.default.post(name: SleepNotification, object: nil) let end = Date() print("相差:\(end.timeIntervalSince(start))")
|
我们可以看到最后相差时间大概是 3s
,通过上面的代码我们就知道单 NotificationCenter 去 post 一个通知的时候,它会等待观察者处理完改通知之后才会继续往后执行。所以平常使用过程中我们要注意 post 有可能会阻塞当前线程,特别是在主线程中。