先看看下面的代码,这两段notiObserver
有区别吗?
override func viewDidLoad() {
super.viewDidLoad()
let noti = Notification(name: MyNotificationName)
var v = 0
let center = NotificationCenter.default
var notiObserver:NSObjectProtocol! = nil
notiObserver = center.addObserver(forName: MyNotificationName, object: nil, queue: .main) {_ in
if v == 10 { center.removeObserver(notiObserver) }
else {
v += 1
center.post(noti)
}
print(v)
}
notiObserver = center.addObserver(forName: MyNotificationName, object: nil, queue: nil) { _ in
DispatchQueue.main.async {
if v == 10 { center.removeObserver(notiObserver) }
else {
v += 1
center.post(noti)
}
print(v)
}
}
center.post(noti)
}
无论你觉得有区别,还是没区别,你可以分别注释掉其中一个然后运行。运行结果是这样的。
上面的那段会输出
10
10
10
10
10
10
10
10
10
10
10
下面那段会输出
1
2
3
4
5
6
7
8
9
10
10
这是为什么呢?我们来看文档。苹果的文档在提到queue
是这么说的。
queue
The operation queue to which block should be added.
If you pass nil, the block is run synchronously on the posting thread.
也就是说,它默认是在队列中同步执行。即便我们换成了.main,它也不是我们以为的是异步执行的。实际上,我们可以测试出来,这段代码,在运行时,是堆栈式的。新到的Notification
,会进行压栈,优先执行。然后才是旧的Notification
没执行完的代码。
如图所示,从左到右是时间轴,依次运行的3段代码,绿色的center.post(noti)
导致黄色被执行,黄色的center.post(noti)
导致蓝色被执行……,一直到v==10
,最后的一段代码print(v)
,才会从上到下执行下来。
结论:如果我们想要代码符合我们的预期的顺序,应该使用第二种方式,通过GCD,将代码加入到顺序执行的queue中去。