NotificationCenter與線程相關(guān)

NotificationCenter是基于iOS程序內(nèi)部之間的一種消息廣播機(jī)制,主要是為了解決應(yīng)用程序不同對(duì)象之間通信解藕而設(shè)計(jì)。它基于KVO模式設(shè)計(jì),當(dāng)收到通知后由通知中心根據(jù)轉(zhuǎn)發(fā)表將消息發(fā)給觀察者。

在Apple的文檔里面有如下說明:

A notification center delivers notifications to observers synchronously. In other words, when posting a notification, control does not return to the poster until all observers have received and processed the notification. To send notifications asynchronously use a notification queue, which is described in Notification Queues.

In a multithreaded application, notifications are always delivered in the thread in which the notification was posted, which may not be the same thread in which an observer registered itself.

其實(shí)它主要是指NotificationCenter是一種“同步的”消息機(jī)制,當(dāng)一個(gè)通知被post之后,他將會(huì)在所有的觀察者都完成了對(duì)應(yīng)的方法后才會(huì)返回。在多線程的應(yīng)用中,通知是在哪個(gè)線程Post就在哪個(gè)線程分發(fā),也就是在同一個(gè)線程被觀察者處理,所以觀察者的回調(diào)函數(shù)是完全由發(fā)送消息的線程決定,而不是由注冊(cè)時(shí)所在的線程決定。

關(guān)于這一點(diǎn)我舉一下我在對(duì)聊天消息進(jìn)行優(yōu)化的時(shí)候發(fā)現(xiàn)的問題作為例子,在原來的代碼結(jié)構(gòu)中,需要處理獲取的消息,并更新會(huì)話cell的排序:

swift

ConversationModel.swift

func handleMessage() {
    var message = Message()
    /* do something to create and process messages */
    NotificationCenter.default.post(name: NSNotification.Name(rawValue: kRefreshConversation), object: self)
}

ConversationVC.swift

func viewDidLoad() {
    NotificationCenter.default.addObserver(self, selector: #selector(refreshConversatin(_:)), name: NSNotification.Name(rawValue: kRefreshConversation), object: nil)
    /* other things ...*/
}

@objc private func refreshConversatin(_ noti: Notification) {
    /* use a long time to sort conversation */
    tableview.reloadData() 
}

在原來這種處理方式中,由于refreshConversation這個(gè)方法會(huì)耗費(fèi)大量時(shí)間,而這個(gè)通知是在主線程發(fā)起的,所以會(huì)導(dǎo)致主線程被阻塞,所以我針對(duì)這個(gè)問題對(duì)ConversationModel進(jìn)行了重構(gòu)。

首先我將Conversation獲取并組裝Message的這一塊內(nèi)容都放置在后臺(tái)線程進(jìn)行,因?yàn)镸odel相關(guān)的操作可能會(huì)占用很多的時(shí)間,放在主線程創(chuàng)建并組裝是不可靠的。當(dāng)message組裝完畢需要更新ConversationVC中的排序時(shí),在ConversationVC中接收到通知后再轉(zhuǎn)到主線程進(jìn)行操作。同時(shí)我在排序的代碼中也進(jìn)行了優(yōu)化,如果ConversationVC沒有被展示的話,就不需要占用主線程調(diào)用tableViewtableView.insertRows方法,僅僅需要在后臺(tái)線程中對(duì)ConversationModel的數(shù)組進(jìn)行排序即可。因?yàn)?code>tableView.insertRows會(huì)占用大量主線程時(shí)間,所以減少使用該方法的頻率,只在必要時(shí)候調(diào)用,將排序等操作放到后臺(tái)線程進(jìn)行是比較好的解決方法。


想了解更多內(nèi)容可以查看我的博客

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 用到的組件 1、通過CocoaPods安裝 2、第三方類庫(kù)安裝 3、第三方服務(wù) 友盟社會(huì)化分享組件 友盟用戶反饋 ...
    SunnyLeong閱讀 14,650評(píng)論 1 180
  • 近期接觸項(xiàng)目中用的通知比較多,對(duì)于通知有一個(gè)系統(tǒng)的理解與學(xué)習(xí),已下是做的一些總結(jié) 先來看看官方的文檔,是這樣寫的:...
    9de75b652cd9閱讀 607評(píng)論 0 0
  • 艾,指的是艾葉,艾葉純陽,通12經(jīng)絡(luò),理氣血、逐寒濕、暖子宮。 灸,指用火來長(zhǎng)久的熏烤的意思。 中醫(yī)講熱不入則寒不...
    有時(shí)迷糊閱讀 787評(píng)論 0 0
  • 堅(jiān)持冥想已經(jīng)有一個(gè)多月了,今天算是一個(gè)總結(jié),回顧是為了后面走得更遠(yuǎn)。 1.親愛的門外沒有別人只有自己 很多時(shí)候,會(huì)...
    萌媽育兒記閱讀 1,289評(píng)論 2 7
  • 消費(fèi)者剩余是幾年前看曼昆《經(jīng)濟(jì)學(xué)原理》時(shí)的一個(gè)概念,其實(shí)當(dāng)時(shí)對(duì)此概念的實(shí)際場(chǎng)景中的應(yīng)用并不深刻,只記得曼昆是以飛機(jī)...
    Piemon07閱讀 1,626評(píng)論 0 2