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的显示


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

=================================================================
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 <redacted> + 20
7   CoreFoundation                      0x00000001c3a8b034 <redacted> + 64
8   CoreFoundation                      0x00000001c3a8a720 <redacted> + 392
9   CoreFoundation                      0x00000001c3a8a3cc <redacted> + 96
10  CoreFoundation                      0x00000001c3afe060 <redacted> + 1404
11  CoreFoundation                      0x00000001c39da164 _CFXNotificationPost + 384
12  Foundation                          0x00000001c44583b4 <redacted> + 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 <redacted> + 20
7   CoreFoundation                      0x00000001c3a8b034 <redacted> + 64
8   CoreFoundation                      0x00000001c3a8a720 <redacted> + 392
9   CoreFoundation                      0x00000001c3a8a3cc <redacted> + 96
10  CoreFoundation                      0x00000001c3afe060 <redacted> + 1404
11  CoreFoundation                      0x00000001c39da164 _CFXNotificationPost + 384
12  Foundation                          0x00000001c44583b4 <redacted> + 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 <redacted> + 136
    1   libdispatch.dylib                   0x0000000105021338 _dispatch_client_callout + 16
    2   libdispatch.dylib                   0x0000000105022150 dispatch_once_f + 120
    3   UIKitCore                           0x00000001efeaeb30 <redacted> + 100
    4   UIKitCore                           0x00000001efeaecb8 <redacted> + 92
    5   UIKitCore                           0x00000001f01278f0 <redacted> + 372
    6   UIKitCore                           0x00000001f01279e4 <redacted> + 32
    7   QuartzCore                          0x00000001c8272c60 <redacted> + 332
    8   QuartzCore                          0x00000001c81d34fc <redacted> + 328
    9   QuartzCore                          0x00000001c8200d74 <redacted> + 596
    10  QuartzCore                          0x00000001c8201514 <redacted> + 252
    11  libsystem_pthread.dylib             0x00000001c3715a58 <redacted> + 584
    12  libsystem_pthread.dylib             0x00000001c37157e8 <redacted> + 80
    13  libsystem_pthread.dylib             0x00000001c3721058 <redacted> + 80
    14  libsystem_pthread.dylib             0x00000001c3715550 _pthread_wqthread + 368
    15  libsystem_pthread.dylib             0x00000001c371536c start_wqthread + 4
)

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


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


运行程序,5秒后界面得到及时更新,所以在使用通知的时候,需要确定接收通知是否会进行UI操作,如果需要操作UI,则在主线程发送通知(封装后比较方便)或者接收通知后在主线程更新UI。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353