内射老阿姨1区2区3区4区_久久精品人人做人人爽电影蜜月_久久国产精品亚洲77777_99精品又大又爽又粗少妇毛片

ios開(kāi)發(fā)中的設(shè)計(jì)模式,ios開(kāi)發(fā)中的設(shè)計(jì)模式在哪

iOS中常用的幾種設(shè)計(jì)模式

代理模式完成委托方交給的任務(wù),委托方有一些任務(wù)自己不想完成,但是還需要要實(shí)現(xiàn),則將該任務(wù)存放到協(xié)議中,由代理完成.但是代理并不會(huì)主動(dòng)的執(zhí)行任務(wù),需要委托方通知代理。

專注于為中小企業(yè)提供成都做網(wǎng)站、網(wǎng)站制作服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)嘉魚(yú)免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了千余家企業(yè)的穩(wěn)健成長(zhǎng),幫助中小企業(yè)通過(guò)網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。

觀察者模式本質(zhì)上是一種發(fā)布-訂閱模型,用以消除具有不同行為的對(duì)象之間的耦合,通過(guò)這一模式,不同對(duì)象可以協(xié)同工作,同時(shí)它們也可以被復(fù)用于其他地方Observer從Subject訂閱通知,ConcreteObserver實(shí)現(xiàn)重現(xiàn)ObServer并將其重載其update方法。

單例模式可以保證App在程序運(yùn)行中,一個(gè)類只有唯一個(gè)實(shí)例,從而做到節(jié)約內(nèi)存。

在整個(gè)App程序中,這一份資源是共享的。

提供一個(gè)固定的實(shí)例創(chuàng)建方法。

策略模式定義了一系列的算法,并將每一個(gè)算法封裝起來(lái),而且使它們還可以相互替換。策略模式讓算法獨(dú)立于使用它的客戶而獨(dú)立變化。

iOS常用設(shè)計(jì)模式

代理模式:完成委托方的任務(wù),需要聲明代理對(duì)象和指定代理,相對(duì)于block,在需要傳遞參數(shù)的傳值時(shí)優(yōu)先考慮代理。

代理是一對(duì)一的關(guān)系(1個(gè)對(duì)象只能通知1個(gè)對(duì)象發(fā)生了什么事)。

應(yīng)用場(chǎng)景:不同類之間的傳值與回調(diào)。

觀察者模式(通知機(jī)制,KVO機(jī)制):觀察者模式本質(zhì)上是一種發(fā)布-訂閱模型,用以消除具有不同行為的對(duì)象之間的耦合,通過(guò)這一模式,不同對(duì)象可以協(xié)同工作。

通知是一對(duì)多的關(guān)系(1個(gè)通知可以發(fā)送給多個(gè)通知接受對(duì)象)。

應(yīng)用場(chǎng)景:監(jiān)聽(tīng)設(shè)備狀態(tài),自定義鍵盤時(shí)監(jiān)聽(tīng)鍵盤的彈出和隱藏。

單例模式:可以保證App在程序運(yùn)行中,一個(gè)類只有唯一個(gè)實(shí)例。

系統(tǒng)中的單例:UIApplication(應(yīng)用程序?qū)嵗?、NSNotificationCenter(消息中心)、NSFileManager(文件管理)、NSUserDefaults(應(yīng)用程序設(shè)置)、NSURLCache(請(qǐng)求緩存)等。

應(yīng)用場(chǎng)景:功能集中管理的模塊可以封裝為單例,方便外界調(diào)用。

策略模式:定義了一系列的算法,并將每一個(gè)算法封裝起來(lái),而且使它們還可以相互替換。策略模式讓算法獨(dú)立于使用它的客戶而獨(dú)立變化。

MVC(Model View Controller):

model:數(shù)據(jù)層

view:視圖層,負(fù)責(zé)頁(yè)面展示

Controller:控制視圖層與數(shù)據(jù)層的關(guān)聯(lián),

MVVM(model view viewModel):

Model: 數(shù)據(jù)層,不包含邏輯

View:與用戶直接交互,只需處理觸發(fā)事件后的轉(zhuǎn)發(fā),和告訴他如何顯示

ViewModel:跟蹤view的事件,處理model層傳遞的數(shù)據(jù);公開(kāi)方法、屬性,讓view保持最新的狀態(tài)

ios開(kāi)發(fā)的設(shè)計(jì)模式有哪些

iOS開(kāi)發(fā)就是為裝有iOS系統(tǒng)的設(shè)備完成應(yīng)用軟件或游戲軟件的開(kāi)發(fā),ios開(kāi)發(fā)的設(shè)計(jì)模式有代理模式、觀察者模式、MVC模式、單例模式、策略模式和工廠模式。

iOS 設(shè)計(jì)模式(五)-KVO 詳解

KVO 的全稱是 Key-Value Observing,俗稱“鍵值觀察/監(jiān)聽(tīng)”,是蘋果提供的一套事件通知機(jī)制,允許一個(gè)對(duì)象觀察/監(jiān)聽(tīng)另一個(gè)對(duì)象指定屬性值的改變。當(dāng)被觀察對(duì)象屬性值發(fā)生改變時(shí),會(huì)觸發(fā) KVO 的監(jiān)聽(tīng)方法來(lái)通知觀察者。KVO 是在 MVC 應(yīng)用程序中的各層之間進(jìn)行通信的一種特別有用的技術(shù)。

KVO 和 NSNotification 都是 iOS 中觀察者模式的一種實(shí)現(xiàn)。

KVO 可以監(jiān)聽(tīng)單個(gè)屬性的變化,也可以監(jiān)聽(tīng)集合對(duì)象的變化。監(jiān)聽(tīng)集合對(duì)象變化時(shí),需要通過(guò) KVC 的 mutableArrayValueForKey: 等可變代理方法獲得集合代理對(duì)象,并使用代理對(duì)象進(jìn)行操作,當(dāng)代理對(duì)象的內(nèi)部對(duì)象發(fā)生改變時(shí),會(huì)觸發(fā) KVO 的監(jiān)聽(tīng)方法。集合對(duì)象包含 NSArray 和 NSSet 。

先創(chuàng)建一個(gè)類,作為要監(jiān)聽(tīng)的對(duì)象。

監(jiān)聽(tīng)實(shí)現(xiàn)

KVO 主要用來(lái)做鍵值觀察操作,想要一個(gè)值發(fā)生改變后通知另一個(gè)對(duì)象,則用 KVO 實(shí)現(xiàn)最為合適。斯坦福大學(xué)的 iOS 教程中有一個(gè)很經(jīng)典的案例,通過(guò) KVO 在 Model 和 Controller 之間進(jìn)行通信。如圖所示:

KVO 觸發(fā)分為自動(dòng)觸發(fā)和手動(dòng)觸發(fā)兩種方式。

如果是監(jiān)聽(tīng)對(duì)象特定屬性值的改變,通過(guò)以下方式改變屬性值會(huì)觸發(fā) KVO:

如果是監(jiān)聽(tīng)集合對(duì)象的改變,需要通過(guò) KVC 的 mutableArrayValueForKey: 等方法獲得代理對(duì)象,并使用代理對(duì)象進(jìn)行操作,當(dāng)代理對(duì)象的內(nèi)部對(duì)象發(fā)生改變時(shí),會(huì)觸發(fā) KVO。集合對(duì)象包含 NSArray 和 NSSet 。

普通對(duì)象屬性或是成員變量使用:

NSArray 對(duì)象使用:

NSSet 對(duì)象使用:

observationInfo 屬性是 NSKeyValueObserving.h 文件中系統(tǒng)通過(guò)分類給 NSObject 添加的屬性,所以所有繼承于 NSObject 的對(duì)象都含有該屬性;

可以通過(guò) observationInfo 屬性查看被觀察對(duì)象的全部觀察信息,包括 observer 、 keyPath 、 options 、 context 等。

注冊(cè)方法 addObserver:forKeyPath:options:context: 中的 context 可以傳入任意數(shù)據(jù),并且可以在監(jiān)聽(tīng)方法中接收到這個(gè)數(shù)據(jù)。

context 作用:標(biāo)簽-區(qū)分,可以更精確的確定被觀察對(duì)象屬性,用于繼承、 多監(jiān)聽(tīng);也可以用來(lái)傳值。

KVO 只有一個(gè)監(jiān)聽(tīng)回調(diào)方法 observeValueForKeyPath:ofObject:change:context: ,我們通常情況下可以在注冊(cè)方法中指定 context 為 NULL ,并在監(jiān)聽(tīng)方法中通過(guò) object 和 keyPath 來(lái)判斷觸發(fā) KVO 的來(lái)源。

但是如果存在繼承的情況,比如現(xiàn)在有 Person 類和它的兩個(gè)子類 Teacher 類和 Student 類,person、teacher 和 student 實(shí)例對(duì)象都對(duì)象的 name 屬性進(jìn)行觀察。問(wèn)題:

當(dāng) name 發(fā)生改變時(shí),應(yīng)該由誰(shuí)來(lái)處理呢?

如果都由 person 來(lái)處理,那么在 Person 類的監(jiān)聽(tīng)方法中又該怎么判斷是自己的事務(wù)還是子類對(duì)象的事務(wù)呢?

這時(shí)候通過(guò)使用 context 就可以很好地解決這個(gè)問(wèn)題,在注冊(cè)方法中為 context 設(shè)置一個(gè)獨(dú)一無(wú)二的值,然后在監(jiān)聽(tīng)方法中對(duì) context 值進(jìn)行檢驗(yàn)即可。

蘋果的推薦用法:用 context 來(lái)精確的確定被觀察對(duì)象屬性,使用唯一命名的靜態(tài)變量的地址作為 context 的值??梢詾檎麄€(gè)類設(shè)置一個(gè) context ,然后在監(jiān)聽(tīng)方法中通過(guò) object 和 keyPath 來(lái)確定被觀察屬性,這樣存在繼承的情況就可以通過(guò) context 來(lái)判斷;也可以為每個(gè)被觀察對(duì)象屬性設(shè)置不同的 context ,這樣使用 context 就可以精確的確定被觀察對(duì)象屬性。

context 優(yōu)點(diǎn):嵌套少、性能高、更安全、擴(kuò)展性強(qiáng)。

context 注意點(diǎn):

KVO 可以監(jiān)聽(tīng)單個(gè)屬性的變化,也可以監(jiān)聽(tīng)集合對(duì)象的變化。監(jiān)聽(tīng)集合對(duì)象變化時(shí),需要通過(guò) KVC 的 mutableArrayValueForKey: 等方法獲得代理對(duì)象,并使用代理對(duì)象進(jìn)行操作,當(dāng)代理對(duì)象的內(nèi)部對(duì)象發(fā)生改變時(shí),會(huì)觸發(fā) KVO 的監(jiān)聽(tīng)方法。集合對(duì)象包含 NSArray 和 NSSet 。(注意:如果直接對(duì)集合對(duì)象進(jìn)行操作改變,不會(huì)觸發(fā) KVO。)

可以在被觀察對(duì)象的類中重寫(xiě) + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key 方法來(lái)控制 KVO 的自動(dòng)觸發(fā)。

如果我們只允許外界觀察 person 的 name 屬性,可以在 Person 類如下操作。這樣外界就只能觀察 name 屬性,即使外界注冊(cè)了對(duì) person 對(duì)象其它屬性的監(jiān)聽(tīng),那么在屬性發(fā)生改變時(shí)也不會(huì)觸發(fā) KVO。

也可以實(shí)現(xiàn)遵循命名規(guī)則為 + (BOOL)automaticallyNotifiesObserversOfKey 的方法來(lái)單一控制屬性的 KVO 自動(dòng)觸發(fā),Key 為屬性名(首字母大寫(xiě))。

使用場(chǎng)景:

使用 KVO 監(jiān)聽(tīng)成員變量值的改變;

在某些需要控制監(jiān)聽(tīng)過(guò)程的場(chǎng)景下。比如:為了盡量減少不必要的觸發(fā)通知操作,或者當(dāng)多個(gè)更改同時(shí)具備的時(shí)候才調(diào)用屬性改變的監(jiān)聽(tīng)方法。

由于 KVO 的本質(zhì),重寫(xiě) setter 方法來(lái)達(dá)到可以通知所有觀察者對(duì)象的目的,所以只有通過(guò) setter 方法或 KVC 方法去修改屬性變量值的時(shí)候,才會(huì)觸發(fā) KVO,直接修改成員變量不會(huì)觸發(fā) KVO。

當(dāng)我們要使用 KVO 監(jiān)聽(tīng)成員變量值改變的時(shí)候,可以通過(guò)在為成員變量賦值的前后手動(dòng)調(diào)用 willChangeValueForKey: 和 didChangeValueForKey: 兩個(gè)方法來(lái)手動(dòng)觸發(fā) KVO,如:

NSKeyValueObservingOptionPrior (分別在值改變前后觸發(fā)方法,即一次修改有兩次觸發(fā))的兩次觸發(fā)分別在 willChangeValueForKey: 和 didChangeValueForKey: 的時(shí)候進(jìn)行的。

如果注冊(cè)方法中 options 傳入 NSKeyValueObservingOptionPrior ,那么可以通過(guò)只調(diào)用 willChangeValueForKey: 來(lái)觸發(fā)改變前的那次 KVO,可以用于在屬性值即將更改前做一些操作。

有時(shí)候我們可能會(huì)有這樣的需求,KVO 監(jiān)聽(tīng)的屬性值修改前后相等的時(shí)候,不觸發(fā) KVO 的監(jiān)聽(tīng)方法,可以結(jié)合 KVO 的自動(dòng)觸發(fā)控制和手動(dòng)觸發(fā)來(lái)實(shí)現(xiàn)。

例如:對(duì) person 對(duì)象的 name 屬性注冊(cè)了 KVO 監(jiān)聽(tīng),我們希望在對(duì) name 屬性賦值時(shí)做一個(gè)判斷,如果新值和舊值相等,則不觸發(fā) KVO,可以在 Person 類中如下這樣實(shí)現(xiàn),將 name 屬性值改變的 KVO 觸發(fā)方式由自動(dòng)觸發(fā)改為手動(dòng)觸發(fā)。

有些情況下我們想手動(dòng)觀察集合屬性,下面以觀察數(shù)組為例。

關(guān)鍵方法:

需要注意的是,根據(jù) KVC 的 NSMutableArray 搜索模式:

有些情況下,一個(gè)屬性的改變依賴于別的一個(gè)或多個(gè)屬性的改變,也就是說(shuō)當(dāng)別的屬性改了,這個(gè)屬性也會(huì)跟著改變。

比如我們想要對(duì) Download 類中的 downloadProgress 屬性進(jìn)行 KVO 監(jiān)聽(tīng),該屬性的改變依賴于 writtenData 和 totalData 屬性的改變。觀察者監(jiān)聽(tīng)了 downloadProgress ,當(dāng) writtenData 和 totalData 屬性值改變時(shí),觀察者也應(yīng)該被通知。以下有兩種方法可以解決這個(gè)問(wèn)題。

以上兩個(gè)方法可以同時(shí)存在,且都會(huì)調(diào)用,但是最終結(jié)果會(huì)以 keyPathsForValuesAffectingValueForKey: 為準(zhǔn)。

以上方法在觀察集合屬性時(shí)就不管用了。例如,假如你有一個(gè) Department 類,它有一個(gè)裝有 Employee 類的實(shí)例對(duì)象的數(shù)組,Employee 類有 salary 屬性。你希望 Department 類有一個(gè) totalSalary 屬性來(lái)計(jì)算所有員工的薪水,也就是在這個(gè)關(guān)系中 Department 的 totalSalary 依賴于所有 Employee 實(shí)例對(duì)象的 salary 屬性。以下有兩種方法可以解決這個(gè)問(wèn)題。

有時(shí)候我們難以避免多次注冊(cè)和移除相同的 KVO,或者移除了一個(gè)未注冊(cè)的觀察者,從而產(chǎn)生可能會(huì)導(dǎo)致 Crash 的風(fēng)險(xiǎn)。

三種解決方案: 黑科技防止多次添加刪除KVO出現(xiàn)的問(wèn)題

我們?cè)趯?duì)象添加監(jiān)聽(tīng)之前分別打印對(duì)象類型

我們看到,添加監(jiān)聽(tīng)后,使用 object_getClass 方法獲取model類型時(shí)獲取到的是 NSKVONotifying_DJModel 。

這里就產(chǎn)生了幾個(gè)問(wèn)題:

從打印結(jié)果可以看出, NSKVONotifying_DJModel 是 DJModel 的子類,說(shuō)明我們添加了監(jiān)聽(tīng)之后動(dòng)態(tài)創(chuàng)建了一個(gè) DJModel 的子類 NSKVONotifying_DJModel ,并將對(duì)象 DJModel 的類型更改為了 NSKVONotifying_DJModel 。

我們從源碼看出,實(shí)例對(duì)象調(diào)用 class 方法會(huì)返回 isa 指針,類對(duì)象調(diào)用 class 方法會(huì)返回自己,通過(guò) object_getClass 方法獲取對(duì)象的類型也會(huì)返回 isa 指針。從源碼上看model對(duì)象添加監(jiān)聽(tīng)之后使用 class 和使用 object_getClass 方法獲取到的類型應(yīng)該是一樣的,但是這里卻不同,我們猜測(cè)在添加了監(jiān)聽(tīng)之后在 NSKVONotifying_DJModel 中重寫(xiě)了 class 方法。

我們打印一下添加監(jiān)聽(tīng)前后 class 方法的 IMP 地址來(lái)確認(rèn)是否重寫(xiě)了 class 方法。

從打印結(jié)果可以看出,添加監(jiān)聽(tīng)之后 class 方法的地址改變了,這驗(yàn)證了我們之前的猜想, NSKVONotifying_DJModel 類中重寫(xiě)了 class 方法。

我們監(jiān)聽(tīng)對(duì)象時(shí)調(diào)用了 set 方法,我們對(duì)監(jiān)聽(tīng)前后的 set 方法單獨(dú)分析。

我們?cè)偬砑颖O(jiān)聽(tīng)前后分別打印 setName 方法的 IMP 地址。

通過(guò)打印結(jié)果可以看出 setName 方法也在 NSKVONotifying_DJModel 中被重寫(xiě)了,我們?cè)偈褂胠ldb來(lái)看下 setName 具體是什么

第一個(gè)地址打印的是添加監(jiān)聽(tīng)前 setName 方法的 IMP 地址,第二個(gè)打印的是添加監(jiān)聽(tīng)后 setName 方法的 IMP 地址。

這里看出添加監(jiān)聽(tīng)前 setName 對(duì)應(yīng)的具體方法就是 setName ,但是添加監(jiān)聽(tīng)后, setName 對(duì)應(yīng)的雞頭方法卻變成了 _NSSetObjectValueAndNotify 函數(shù)。

下面我們就來(lái)研究一下 _NSSetObjectValueAndNotify 函數(shù)。

從上面與KVO相關(guān)的方法中我們可以看出,每一種數(shù)據(jù)類型都對(duì)應(yīng)了一個(gè) setXXXValueAndNotify 函數(shù)。

不過(guò)這些函數(shù)的具體實(shí)現(xiàn)沒(méi)有公布,所以內(nèi)部構(gòu)造這里還是不清楚。

但是我們知道,在調(diào)用 `setXXXValueAndNotify 函數(shù)的過(guò)程中會(huì)調(diào)用另外兩個(gè)方法。

測(cè)試后得出了以下幾個(gè)結(jié)論:

我們還可以利用這兩個(gè)方法手動(dòng)觸發(fā) observeValueForKeyPath 方法:

所以我們判斷在 _NSSetObjectValueAndNotify 函數(shù)內(nèi)部,在調(diào)用原來(lái)的 set 方法之前插入了 willChangeValueForKey 方法,在調(diào)用原來(lái)的 set 方法之后插入了 didChangeValueForKey 方法,并根據(jù)初始化時(shí)的枚舉值決定調(diào)用 observeValueForKeyPath 的時(shí)機(jī)。

(1)添加監(jiān)聽(tīng)時(shí),會(huì)動(dòng)態(tài)創(chuàng)建一個(gè)監(jiān)聽(tīng)對(duì)象類型的子類,并將監(jiān)聽(tīng)對(duì)象的 isa 指針指向新的子類。

(2)子類中重寫(xiě)了 class 和監(jiān)聽(tīng)屬性的 set 方法。

(3)重寫(xiě) class 方法是為了不將動(dòng)態(tài)創(chuàng)建的類型暴露出來(lái)。

(4)重寫(xiě) set 方法是將 set 方法的具體實(shí)現(xiàn)替換成了與屬性類型相關(guān)的 __NSSetXXXValueAndNotify 函數(shù)。

(5)在 __NSSetXXXValueAndNotify 函數(shù)內(nèi)部在 set 方法前后分別插入了 willChangeValueForKey 和 didChangeValueForKey 這兩個(gè)方法。

(6)根據(jù)添加監(jiān)聽(tīng)時(shí)的枚舉值決定調(diào)用 observeValueForKeyPath 的具體時(shí)機(jī)。

網(wǎng)頁(yè)標(biāo)題:ios開(kāi)發(fā)中的設(shè)計(jì)模式,ios開(kāi)發(fā)中的設(shè)計(jì)模式在哪
當(dāng)前鏈接:http://m.rwnh.cn/article30/phjeso.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制開(kāi)發(fā)、動(dòng)態(tài)網(wǎng)站網(wǎng)站改版、軟件開(kāi)發(fā)、搜索引擎優(yōu)化

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都網(wǎng)頁(yè)設(shè)計(jì)公司
吴旗县| 华阴市| 永德县| 湄潭县| 兴城市| 汾阳市| 萨迦县| 军事| 财经| 崇仁县| 河间市| 吉林市| 田东县| 安宁市| 松阳县| 繁峙县| 通山县| 永丰县| 隆回县| 吴川市| 兖州市| 称多县| 东方市| 天门市| 霍山县| 夏津县| 贺兰县| 宁阳县| 吴堡县| 福清市| 广西| 石河子市| 辽宁省| 防城港市| 渝北区| 壤塘县| 山阴县| 岱山县| 海安县| 兴和县| 聂拉木县|