<del id="d4fwx"><form id="d4fwx"></form></del>
      <del id="d4fwx"><form id="d4fwx"></form></del><del id="d4fwx"><form id="d4fwx"></form></del>

            <code id="d4fwx"><abbr id="d4fwx"></abbr></code>
          • ios開發(fā)中的設(shè)計模式,ios開發(fā)中的設(shè)計模式在哪

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

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

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

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

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

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

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

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

            iOS常用設(shè)計模式

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

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

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

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

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

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

            單例模式:可以保證App在程序運行中,一個類只有唯一個實例。

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

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

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

            MVC(Model View Controller):

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

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

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

            MVVM(model view viewModel):

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

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

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

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

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

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

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

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

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

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

            監(jiān)聽實現(xiàn)

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

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

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

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

            普通對象屬性或是成員變量使用:

            NSArray 對象使用:

            NSSet 對象使用:

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

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

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

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

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

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

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

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

            這時候通過使用 context 就可以很好地解決這個問題,在注冊方法中為 context 設(shè)置一個獨一無二的值,然后在監(jiān)聽方法中對 context 值進行檢驗即可。

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

            context 優(yōu)點:嵌套少、性能高、更安全、擴展性強。

            context 注意點:

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

            可以在被觀察對象的類中重寫 + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key 方法來控制 KVO 的自動觸發(fā)。

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

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

            使用場景:

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

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

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

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

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

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

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

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

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

            關(guān)鍵方法:

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

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

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

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

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

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

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

            我們在對象添加監(jiān)聽之前分別打印對象類型

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

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

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

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

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

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

            我們監(jiān)聽對象時調(diào)用了 set 方法,我們對監(jiān)聽前后的 set 方法單獨分析。

            我們再添加監(jiān)聽前后分別打印 setName 方法的 IMP 地址。

            通過打印結(jié)果可以看出 setName 方法也在 NSKVONotifying_DJModel 中被重寫了,我們再使用lldb來看下 setName 具體是什么

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

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

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

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

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

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

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

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

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

            (1)添加監(jiān)聽時,會動態(tài)創(chuàng)建一個監(jiān)聽對象類型的子類,并將監(jiān)聽對象的 isa 指針指向新的子類。

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

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

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

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

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

            網(wǎng)頁標(biāo)題:ios開發(fā)中的設(shè)計模式,ios開發(fā)中的設(shè)計模式在哪
            當(dāng)前鏈接:http://www.jbt999.com/article30/phjeso.html

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

            廣告

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

            成都網(wǎng)頁設(shè)計公司

              <del id="d4fwx"><form id="d4fwx"></form></del>
              <del id="d4fwx"><form id="d4fwx"></form></del><del id="d4fwx"><form id="d4fwx"></form></del>

                    <code id="d4fwx"><abbr id="d4fwx"></abbr></code>
                  • 丰满级A片直播免费下载观看 | 成人视频三级A片 | 亚洲AV成人无码精品直播在线 | 国产一级黄色录像 | 青青草免费视频在线 |