真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

ios開發(fā)原理,iOS三大設(shè)計(jì)原理

iOS開發(fā) - NSNotification原理理解

NSNotification是iOS中一個(gè)調(diào)度消息通知的類,采用單例設(shè)計(jì)模式,在開發(fā)中實(shí)現(xiàn)傳值、回調(diào)等。在iOS中,NSNotification是使用觀察者模式來實(shí)現(xiàn)用于跨層傳遞消息。

創(chuàng)新互聯(lián)公司主要從事成都網(wǎng)站建設(shè)、成都做網(wǎng)站、網(wǎng)頁設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)涪城,十余年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):18982081108

NSNotification包含了一些用于向其他對(duì)象發(fā)送通知的必要信息,包括名稱、對(duì)象和可選字典,并由NSNotificationCenter或NSDistributedNotificationCenter的實(shí)例進(jìn)行發(fā)送。name是標(biāo)識(shí)通知的標(biāo)記、object是保存發(fā)送通知的對(duì)象、userinfo存儲(chǔ)其他相關(guān)對(duì)象。 這里主要注意的是:NSNotification對(duì)象是不可變的。

可以使用 notificationWithName:object: 或 notificationWithName:object:userInfo: 創(chuàng)建通知對(duì)象。但實(shí)際開發(fā)中,一般是直接使用NSNotificationCenter調(diào)用 postNotificationName:object: 或 postNotificationName:object:userInfo: ,這兩個(gè)類方法會(huì)在內(nèi)部直接創(chuàng)建NSNotification對(duì)象,并發(fā)出通知。

??從官網(wǎng)文檔可知,NSNotification是不能直接實(shí)例化的,如果用init方法進(jìn)行實(shí)例化時(shí),會(huì)引發(fā)異常。還有需要注意的是如果我們自己去實(shí)現(xiàn)構(gòu)造方法時(shí),不能在super上調(diào)用init方法。

NSNotificationCenter提供了一套機(jī)制來發(fā)送通知,每個(gè)運(yùn)行中的應(yīng)用程序都有一個(gè)defaultCenter通知中心,我們可以創(chuàng)建新的通知中心來組織特定上下文中的通信。??NSNotificationCenter暴露給外部的字段只有一個(gè)defaultCenter,并且該字段是只讀的,暴露出來的方法分為三種:添加、移除通知觀察者和發(fā)出通知。詳細(xì)如下表所示:

postNotificationName:object:

postNotificationName:object:userInfo: |

相關(guān)說明:

簡單理解為:通知中心的緩沖區(qū)。盡管通知中心已經(jīng)分發(fā)通知,但放置到隊(duì)列中的通知可能會(huì)延遲,直到runloop結(jié)束或者runloop空閑時(shí)才發(fā)送。如果有多個(gè)相同的通知,NSNotificationQueue會(huì)將其進(jìn)行合并,以便在發(fā)布多個(gè)通知的情況下只發(fā)送一個(gè)通知。

??通知隊(duì)列按照先進(jìn)先出(FIFO)的順序維護(hù)通知。當(dāng)一個(gè)通知移動(dòng)到隊(duì)列的前面時(shí),隊(duì)列將它發(fā)送到通知中心,然后再將通知分派給所有注冊(cè)為觀察者的對(duì)象。每個(gè)線程都有一個(gè)默認(rèn)的通知隊(duì)列,該隊(duì)列與流程的默認(rèn)通知中心相關(guān)聯(lián)。我們也可以創(chuàng)建自己的通知隊(duì)列。

??和NSNotificationCenter一樣,NSNotificationQueue也只暴露了一個(gè)字段:defaultQueue,返回當(dāng)前線程的默認(rèn)通知隊(duì)列。方法分為:創(chuàng)建通知隊(duì)列和管理通知。詳細(xì)說明如下表所示:

dequeueNotificationsMatching:coalesceMask:

enqueueNotification:postingStyle:coalesceMask:forModes: |

方法相關(guān)說明:

在上面的方法中,需要注意的2個(gè)常量,相關(guān)說明如下:

NSNotificationCenter定義了兩個(gè)Table,同時(shí)為了封裝觀察者信息,也定義了Observation保存觀察者信息。他們的結(jié)構(gòu)體可以簡化如下所示:

在NSNotificationCenter內(nèi)部一共保存了兩張表,一張用于保存添加觀察者的時(shí)候傳入的NotificationName的情況;一張用于保存添加觀察者的時(shí)候沒有傳入NotificationCenter的情況,詳細(xì)分析如下:

在Named Table中,NotificationName作為表的key,因?yàn)槲覀冊(cè)谧?cè)觀察者的時(shí)候是可以傳入一個(gè)object參數(shù)用于只監(jiān)聽該對(duì)象發(fā)出的通知,并且一個(gè)通知可以添加多個(gè)觀察者,所以還需要一張表用來保存object和observe的對(duì)應(yīng)關(guān)系。這張表的key、value分別是以object為key,observe為value。所以對(duì)于Named Table,最終的結(jié)構(gòu)為:

Named Table

特別說明:在實(shí)際開發(fā)中,我們經(jīng)常將object參數(shù)傳nil,這個(gè)時(shí)候系統(tǒng)會(huì)根據(jù)nil自動(dòng)產(chǎn)生一個(gè)key。相當(dāng)于這個(gè)key對(duì)應(yīng)的value(鏈表)保存的就是對(duì)于當(dāng)前NotificationName沒有傳入object的所有觀察者。當(dāng)NotificationName被發(fā)送時(shí),在鏈表中的觀察者都會(huì)收到通知。

UNamed Table結(jié)構(gòu)比Named Table簡單得多。因?yàn)闆]有NotificationName作為key。這里直接就以object為key,比Named Table少了一層Table嵌套。

UnNamed Table

如果在注冊(cè)觀察者時(shí)沒有傳入NotificationName,同時(shí)沒有傳入object,所有的系統(tǒng)通知都會(huì)發(fā)送到注冊(cè)的對(duì)象里。

首先在初始化NSNotificationCenter時(shí)會(huì)創(chuàng)建一個(gè)對(duì)象,這個(gè)對(duì)象里面保存了Named Table、UNamed Table和其他信息。

在沒有傳入NotificationName的情況和上面的過程類似,只不過是直接根據(jù)object去對(duì)應(yīng)的鏈表而已。如果既沒有傳入NotificationName,也沒有傳入object,則這個(gè)觀察者會(huì)添加到wildcard鏈表中。

發(fā)送通知一般是調(diào)用 postNotificationName:object:userInfo: 方法來實(shí)現(xiàn)。該方法內(nèi)部會(huì)實(shí)例化一個(gè)NSNotification來保存?zhèn)魅氲母鞣N參數(shù),包括name、object和userinfo。

??發(fā)送通知的流程總體來說就是根據(jù)NotificationName查找到對(duì)應(yīng)的Observer鏈表,然后遍歷整個(gè)鏈表,給每個(gè)Observer結(jié)點(diǎn)中保存的對(duì)象及SEL,來向?qū)ο蟀l(fā)送消息。具體流程如下:

這個(gè)方式也就能說明,發(fā)送通知的線程和接收通知的線程都是同一個(gè)線程。

NSNotification和線程同步之間是什么關(guān)系呢?先看下官方文檔的說明:

翻譯過來意思為:

更多關(guān)于NSNotification與線程之間的關(guān)系,請(qǐng)閱讀下面的文章: iOS開發(fā) - NSNotification和線程相關(guān)

總的來說,NSNotification的三個(gè)相關(guān)類的作用,可以用下圖進(jìn)行歸納總結(jié)。

總結(jié)

IOS基礎(chǔ)原理:Notifications

用于異步發(fā)送消息的通知隊(duì)列,這個(gè)異步并不是開啟線程,而是把通知存到雙向鏈表實(shí)現(xiàn)的隊(duì)列里面,等待某個(gè)時(shí)機(jī)觸發(fā)。觸發(fā)時(shí)調(diào)用 NSNotificationCenter 的發(fā)送接口進(jìn)行發(fā)送通知,這么看 NSNotificationQueue 最終還是調(diào)用 NSNotificationCenter 進(jìn)行消息的分發(fā),另外 NSNotificationQueue 是依賴 runloop 的,所以如果線程的 runloop 未開啟則無效。

把通知添加到隊(duì)列等待發(fā)送,同時(shí)提供了一些附加條件供開發(fā)者選擇,如:什么時(shí)候發(fā)送通知、如何合并通知等,系統(tǒng)給了如下定義。

可以,因?yàn)?notificationcenter 對(duì)觀察者的引用是 weak ,當(dāng)觀察者釋放的時(shí)候,觀察者的指針值被置為 nil

會(huì)調(diào)用多次 observer 的 action 。多次移除沒有任何影響。

NCTable 結(jié)構(gòu)體中核心的三個(gè)變量: wildcard 、 named 、 nameless ,在源碼中直接用宏定義表示了: WILDCARD 、 NAMELESS 、 NAMED 。

? NAMED 是個(gè)宏,表示名為 named 的字典。如果通知的 name 存在,則以 name 為 key 從 named 字典中取出值 n (這個(gè) n 其實(shí)被 MapNode 包裝了一層,便于理解這里直接認(rèn)為沒有包裝),這個(gè) n 還是個(gè)字典。

? n 不存在,則先取緩存,如果緩存沒有則新建一個(gè) map

? n 存在則把值取出來賦值給 m

? 然后以 object 為 key ,從字典中取出對(duì)應(yīng)的值,這個(gè)值就是 Observation 類型的鏈表,然后把剛開始創(chuàng)建的 Observation 對(duì)象 o 存儲(chǔ)進(jìn)去。

? 以 object 為 key ,從 nameless 字典中取出對(duì)應(yīng)的 value , value 是個(gè)鏈表結(jié)構(gòu)。

? 不存在則新建鏈表,并存到 map 中

? 存在則把值接到鏈表的節(jié)點(diǎn)上

如果注冊(cè)通知時(shí)傳入 name ,那么會(huì)是一個(gè)雙層的存儲(chǔ)結(jié)構(gòu)。首先找到 NCTable 中的 named 表,這個(gè)表存儲(chǔ)了 name 的通知。接著以 name 作為 key ,找到 value ,這個(gè) value 依然是一個(gè) map 。最后, map 的結(jié)構(gòu)是以 object 作為 key , Observation 對(duì)象為 value ,這個(gè) Observation 對(duì)象的結(jié)構(gòu)上面已經(jīng)解釋,主要存儲(chǔ)了 observer SEL 。

以 object 為 key ,從 nameless 字典中取出 value ,此 value 是個(gè) Observation 類型的鏈表。接著把創(chuàng)建的 Observation 類型的對(duì)象 o 存儲(chǔ)到鏈表中。只存在 object 時(shí)存儲(chǔ)只有一層,那就是 object 和 Observation 對(duì)象之間的映射。

這種情況直接把 Observation 對(duì)象存放在了 Observation *wildcard 鏈表結(jié)構(gòu)中。

發(fā)送通知的核心邏輯比較簡單,基本上就是查找和調(diào)用響應(yīng)方法,從三個(gè)存儲(chǔ)容器中: named 、 nameless 、 wildcard 去查找對(duì)應(yīng)的 Observation 對(duì)象,然后通過 performSelector :逐一調(diào)用響應(yīng)方法,這就完成了發(fā)送流程。

主要做了三件事:查找通知、發(fā)送、釋放資源。

? 通過 name object 從 named 、 nameless 、 wildcard 表中查找對(duì)應(yīng)的通知(保存了 observer 和 sel )。

? 執(zhí)行發(fā)送,即調(diào)用 performSelector 執(zhí)行響應(yīng)方法,從這里可以看出是同步的。

? 釋放 notification 對(duì)象。

因?yàn)椴檎視r(shí)做了這個(gè)鏈表的遍歷,所以刪除時(shí)會(huì)把重復(fù)的通知全都刪除掉

查找時(shí)仍然以 name 和 object 為準(zhǔn),再加上 observer 做區(qū)分。

上面介紹的 NSNotificationCenter 都是同步發(fā)送的,接受消息和發(fā)送消息是在一個(gè)線程里。這里介紹關(guān)于 NSNotificationQueue 的異步發(fā)送,通過 NSNotificationQueue 將通知添加到隊(duì)列當(dāng)中,立即將控制權(quán)返回給調(diào)用者,在合適的時(shí)機(jī)發(fā)送通知,從而不會(huì)阻塞當(dāng)前的調(diào)用。從線程的角度看并不是真正的異步發(fā)送,或可稱為延時(shí)發(fā)送,它是利用了 runloop 的時(shí)機(jī)來觸發(fā)的,所以如果在其他子線程使用 NSNotificationQueue ,需要開啟 runloop 。由于最終還是通過 NSNotificationCenter 進(jìn)行發(fā)送通知,所以從這個(gè)角度講它還是同步的。所謂異步,指的是非實(shí)時(shí)發(fā)送而是在合適的時(shí)機(jī)發(fā)送,并沒有開啟異步線程。

NSPostingStyle 和 coalesceMask 在上面的類結(jié)構(gòu)中有介紹。 modes 這個(gè)就和 runloop 有關(guān)了,指的是 runloop 的 mode 。

? 根據(jù) coalesceMask 參數(shù)判斷是否合并通知

? 接著根據(jù) postingStyle 參數(shù),判斷通知發(fā)送的時(shí)機(jī)

? runloop 立即回調(diào)通知方法,同步發(fā)送

? runloop 在執(zhí)行 timer 事件或 sources 事件的時(shí)候回調(diào)通知方法,異步發(fā)送

? runloop 空閑的時(shí)候回調(diào)通知方法,異步發(fā)送

runloop 觸發(fā)某個(gè)時(shí)機(jī),調(diào)用 GSPrivateNotifyASAP() 和 GSPrivateNotifyIdle() 方法,這兩個(gè)方法最終都調(diào)用了 notify() 方法。 notify() 所做的事情就是調(diào)用 NSNotificationCenter 的 postNotification: 進(jìn)行發(fā)送通知。

異步線程發(fā)送通知?jiǎng)t響應(yīng)函數(shù)也是在異步線程,如果執(zhí)行UI刷新相關(guān)的話就會(huì)出現(xiàn)問題,那么如何保證在主線程響應(yīng)通知呢?可以使用 addObserverForName: object: queue: usingBlock 方法注冊(cè)通知,指定在 mainqueue 上響應(yīng) block 。

ios閱讀器開發(fā)原理

1、首先將 epub 文件解壓后得到其資源文件包,其中會(huì)包含相應(yīng)的文件夾。

2、其次通過 OEBPS 文件夾中的資源文件提取所需的數(shù)據(jù)并進(jìn)行拼裝后渲染,包含了文件的解壓縮和通過 touchXML 對(duì) xml 數(shù)據(jù)的解析和寫入。

3、最后對(duì) xml 解析獲取到節(jié)點(diǎn)內(nèi)容并保存,遍歷數(shù)據(jù)數(shù)組找到其中所需的節(jié)點(diǎn),將其遍歷節(jié)點(diǎn)得到所需屬性的 name 和 value 作為字典對(duì)象填充至模型。


分享題目:ios開發(fā)原理,iOS三大設(shè)計(jì)原理
文章鏈接:http://weahome.cn/article/hoigsg.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部