iOS中关于NotificationCenter通知线程问题

在iOS开发中,NotificationCenter是经常会用到的,我一般发通知会自己封装一个方法,在主线程中进行发送。

func postNotification(name: NSNotification.Name, object: Any?, _ userInfo: [AnyHashable : Any]? = nil){
        DispatchQueue.main.async {
            NotificationCenter.default.post(name: name, object: object, userInfo: userInfo)
        }
    }

因为我的想法是在接收到通知后有可能会操作UI,如果某次发送通知是在子线程(例如网络请求,请求到特定数据后发出通知),接收到通知更新UI,会造成程序崩溃。为了验证这个想法,我做了一个简单的测试。

测试

首先在子线程中发送通知,在接收到通知后更新界面中label的显示


iOS中关于NotificationCenter通知线程问题_第1张图片

运行程序,结果是程序不会崩溃,但是界面并不会更新任何信息,控制台打印信息如下:

=================================================================
Main Thread Checker: UI API called on a background thread: -[UILabel setText:]
PID: 1248, TID: 222437, Thread name: (none), Queue name: com.apple.root.default-qos, QoS: 0
Backtrace:
4   testnoti                            0x000000010420bc68 _T08testnoti14ViewControllerC8updateUIyyF + 200
5   testnoti                            0x000000010420be44 _T08testnoti14ViewControllerC8updateUIyyFTo + 40
6   CoreFoundation                      0x00000001c3a8b068  + 20
7   CoreFoundation                      0x00000001c3a8b034  + 64
8   CoreFoundation                      0x00000001c3a8a720  + 392
9   CoreFoundation                      0x00000001c3a8a3cc  + 96
10  CoreFoundation                      0x00000001c3afe060  + 1404
11  CoreFoundation                      0x00000001c39da164 _CFXNotificationPost + 384
12  Foundation                          0x00000001c44583b4  + 68
13  testnoti                            0x000000010420b9d8 _T08testnoti14ViewControllerC11viewDidLoadyyFyycfU_ + 512
14  testnoti                            0x000000010420ba2c _T0Ix_IyB_TR + 48
15  libdispatch.dylib                   0x0000000105021338 _dispatch_client_callout + 16
16  libdispatch.dylib                   0x000000010502c5e4 _dispatch_continuation_pop + 528
17  libdispatch.dylib                   0x000000010502314c _dispatch_source_invoke + 1880
18  libdispatch.dylib                   0x000000010502bef4 _dispatch_queue_override_invoke + 448
19  libdispatch.dylib                   0x00000001050393ac _dispatch_root_queue_drain + 376
20  libdispatch.dylib                   0x0000000105039db0 _dispatch_worker_thread2 + 156
21  libsystem_pthread.dylib             0x00000001c37155c0 _pthread_wqthread + 480
22  libsystem_pthread.dylib             0x00000001c371536c start_wqthread + 4
2018-07-03 14:14:48.830508+0800 testnoti[1248:222437] [reports] Main Thread Checker: UI API called on a background thread: -[UILabel setText:]
PID: 1248, TID: 222437, Thread name: (none), Queue name: com.apple.root.default-qos, QoS: 0
Backtrace:
4   testnoti                            0x000000010420bc68 _T08testnoti14ViewControllerC8updateUIyyF + 200
5   testnoti                            0x000000010420be44 _T08testnoti14ViewControllerC8updateUIyyFTo + 40
6   CoreFoundation                      0x00000001c3a8b068  + 20
7   CoreFoundation                      0x00000001c3a8b034  + 64
8   CoreFoundation                      0x00000001c3a8a720  + 392
9   CoreFoundation                      0x00000001c3a8a3cc  + 96
10  CoreFoundation                      0x00000001c3afe060  + 1404
11  CoreFoundation                      0x00000001c39da164 _CFXNotificationPost + 384
12  Foundation                          0x00000001c44583b4  + 68
13  testnoti                            0x000000010420b9d8 _T08testnoti14ViewControllerC11viewDidLoadyyFyycfU_ + 512
14  testnoti                            0x000000010420ba2c _T0Ix_IyB_TR + 48
15  libdispatch.dylib                   0x0000000105021338 _dispatch_client_callout + 16
16  libdispatch.dylib                   0x000000010502c5e4 _dispatch_continuation_pop + 528
17  libdispatch.dylib                   0x000000010502314c _dispatch_source_invoke + 1880
18  libdispatch.dylib                   0x000000010502bef4 _dispatch_queue_override_invoke + 448
19  libdispatch.dylib                   0x00000001050393ac _dispatch_root_queue_drain + 376
20  libdispatch.dylib                   0x0000000105039db0 _dispatch_worker_thread2 + 156
21  libsystem_pthread.dylib             0x00000001c37155c0 _pthread_wqthread + 480
22  libsystem_pthread.dylib             0x00000001c371536c start_wqthread + 4
2018-07-03 14:14:56.519094+0800 testnoti[1248:222437] [Animation] +[UIView setAnimationsEnabled:] being called from a background thread. Performing any operation from a background thread on UIView or a subclass is not supported and may result in unexpected and insidious behavior. trace=(
    0   UIKitCore                           0x00000001efeaebbc  + 136
    1   libdispatch.dylib                   0x0000000105021338 _dispatch_client_callout + 16
    2   libdispatch.dylib                   0x0000000105022150 dispatch_once_f + 120
    3   UIKitCore                           0x00000001efeaeb30  + 100
    4   UIKitCore                           0x00000001efeaecb8  + 92
    5   UIKitCore                           0x00000001f01278f0  + 372
    6   UIKitCore                           0x00000001f01279e4  + 32
    7   QuartzCore                          0x00000001c8272c60  + 332
    8   QuartzCore                          0x00000001c81d34fc  + 328
    9   QuartzCore                          0x00000001c8200d74  + 596
    10  QuartzCore                          0x00000001c8201514  + 252
    11  libsystem_pthread.dylib             0x00000001c3715a58  + 584
    12  libsystem_pthread.dylib             0x00000001c37157e8  + 80
    13  libsystem_pthread.dylib             0x00000001c3721058  + 80
    14  libsystem_pthread.dylib             0x00000001c3715550 _pthread_wqthread + 368
    15  libsystem_pthread.dylib             0x00000001c371536c start_wqthread + 4
)

很明显是在告诉我们,操作UI线程错误,必须在主线程操作,在代码中Xcode也给出了提示:


iOS中关于NotificationCenter通知线程问题_第2张图片

现在改动一下代码,使通知在主线程发送


iOS中关于NotificationCenter通知线程问题_第3张图片

运行程序,5秒后界面得到及时更新,所以在使用通知的时候,需要确定接收通知是否会进行UI操作,如果需要操作UI,则必须在主线程发送通知。

你可能感兴趣的:(iOS中关于NotificationCenter通知线程问题)