MVC模式:
M: model 是數(shù)據(jù)模型
V: view 是視圖
C: controller 是控制器
model 與view 不能直接交互产上,需要通過controller來同步
model負(fù)責(zé)數(shù)據(jù)和狀態(tài)的更新弟断,view顯示給用戶看的內(nèi)容
如何通信:
controller到model: 導(dǎo)入model類啄寡,實(shí)例化model對象机杜,進(jìn)行數(shù)據(jù)同步
controller到view: 在controller中創(chuàng)建View的控件outlet屬性進(jìn)行通信view到controller: 不能在view類中實(shí)例化controller碌冶,需要使用target: action目標(biāo)動作機(jī)制或者delegate委托機(jī)制實(shí)現(xiàn)通信
target:action:用戶在view上觸發(fā)事件盅藻,view會產(chǎn)生一個action動作朱盐,在controller中群嗤,通過addtarget:方法,接受action動作兵琳。controller自身設(shè)置target狂秘,view在需要通知controller時向controller發(fā)送action
delegate: controller作為view的被委托者,代理闰围。為view 提供顯示需要的數(shù)據(jù)
分為動作類delegate:在controller中響應(yīng)action動作和data source數(shù)據(jù)源類delegate:為view 提供需要顯示的數(shù)據(jù)model到controller: 不能在model類中實(shí)例化controller赃绊,因為model不知道有多少個controller引用它。
需要使用通知機(jī)制和KVO模式和controller通信
Notification: model自己設(shè)置一個通知中心NSNotificationCenter羡榴,需要知道m(xù)odel數(shù)據(jù)變化的的controller自己注冊一個通知addObserver來監(jiān)聽model的數(shù)據(jù)數(shù)據(jù)變化碧查,讓不需要監(jiān)聽model需要移除注冊監(jiān)聽
KVO: 使用addObserver:forKeyPath:option:context:
方法和removeObserver:forKeyPath:
方法來對model設(shè)置和移除注冊監(jiān)聽
MVC模式的優(yōu)勢:
- 低耦合性
- 高重用性
- 可適用性
- 可維護(hù)性
MVVM的簡單理解:
MVVM模式是MVC模式的增強(qiáng),把MVC中controller里的表示model給view顯示數(shù)據(jù)的表示邏輯部分提取出來了——view model
MVVM 即 model view viewcontroller view model
單例模式:
應(yīng)用程序中的類只擁有一個實(shí)例:
NSApplication NSFileManager NSBundle UserDefault VIAccelermeter
單例易于訪問
實(shí)現(xiàn)單例:
- 在類的內(nèi)部提供一個static修飾的全局變量
- 提供一個類方法,方便外界訪問
- 重寫+allocWithZone方法忠售,保證永遠(yuǎn)都只為單例對象分配一次內(nèi)存空間
- 重寫-copyWithZone方法和-MutableCopyWithZone方法
KVC模式:
KVC概念::KeyValueCoding 鍵值編碼
KVC可以直接通過字符串類型的屬性名key來訪問某個類屬性的機(jī)制传惠,支持對象和基本數(shù)據(jù)類型(自動封裝,解裝)不是通過調(diào)用的Setter稻扬、Getter方法訪問
關(guān)鍵方法定義在 NSKeyValueCodingProtocol
KVC用法:
獲取值
- valueForKey:
卦方,傳入NSString屬性的名字。
- valueForKeyPath:
泰佳,傳入NSString屬性的路徑盼砍,xx.xx形式。
- valueForUndefinedKey
它的默認(rèn)實(shí)現(xiàn)是拋出異常逝她,可以重寫這個函數(shù)做錯誤處理浇坐。
修改值
- setValue:forKey:
- setValue:forKeyPath:
- setValue:forUndefinedKey:
- setNilValueForKey:
當(dāng)對非類對象屬性設(shè)置nil時,調(diào)用黔宛,默認(rèn)拋出異常近刘。
一對多關(guān)系成員的情況
- mutableArrayValueForKey:
有序一對多關(guān)系成員 NSArray
- mutableSetValueForKey:
無序一對多關(guān)系成員 NSSet
鍵值驗證(Key-Value Validation)
KVC提供屬性值確認(rèn)的API,它可以用來檢查set的值是否正確臀晃、為不正確的值做一個替換值或者拒絕設(shè)置新值并返回錯誤原因
調(diào)用核查方法:
- validateValue:forKey:error:
觉渴,默認(rèn)實(shí)現(xiàn)會搜索 validate<Key>:error:
格式的核查方法,找到則調(diào)用徽惋,未找到默認(rèn)返回YES
集合操作:
集合操作通過對valueForKeyPath:傳遞參數(shù)來使用案淋,一定要用在集合(如:array)上,否則產(chǎn)生運(yùn)行時刻錯誤寂曹。其格式如下:
Left keypath部分:需要操作對象路徑哎迄。
Collectionoperator部分:通過@符號確定使用的集合操作回右。
Rightkey path部分:需要進(jìn)行集合操作的屬性隆圆。
- 數(shù)據(jù)操作
@avg:平均值
@count:總數(shù)
@max:最大
@min:最小
@sum:總數(shù)
確保操作的屬性為數(shù)字類型,否則運(yùn)行時刻錯誤翔烁。
- 對象操作
針對數(shù)組的情況
@distinctUnionOfObjects:返回指定屬性去重后的值的數(shù)組
@unionOfObjects:返回指定屬性的值的數(shù)組渺氧,不去重
屬性的值不能為空,否則產(chǎn)生異常蹬屹。 - 數(shù)組操作
針對數(shù)組的數(shù)組情況
@distinctUnionOfArrays:返回指定屬性去重后的值的數(shù)組
@unionOfArrays:返回指定屬性的值的數(shù)組侣背,不去重
@distinctUnionOfSets:同上,只是返回值為NSSet
KVC鍵值查找(搜索單值成員)
- setValue:forKey:
搜索方式
1慨默、首先搜索setKey:方法贩耐。(key指成員變量名,首字母大寫)
2厦取、上面的setter方法沒找到潮太,如果類方法accessInstanceVariablesDirectly
返回YES。那么按 _key,_isKey铡买,key更鲁,iskey的順序搜索成員名。(NSKeyValueCodingCatogery中實(shí)現(xiàn)的類方法奇钞,默認(rèn)實(shí)現(xiàn)為返回YES)
3澡为、如果沒有找到成員變量,調(diào)用setValue:forUnderfinedKey:
- valueForKey:
的搜索方式
1景埃、首先按getKey媒至,key,isKey的順序查找getter方法谷徙,找到直接調(diào)用塘慕。如果是BOOL、int等內(nèi)建值類型蒂胞,會做NSNumber的轉(zhuǎn)換
2图呢、上面的getter沒找到,查找countOfKey骗随、objectInKeyAtindex蛤织、KeyAtindexes格式的方法。如果countOfKey和另外兩個方法中的一個找到鸿染,那么就會返回一個可以響應(yīng)NSArray所有方法的代理集合的NSArray消息方法
3指蚜、還沒找到,查找countOfKey涨椒、enumeratorOfKey摊鸡、memberOfKey格式的方法。如果這三個方法都找到蚕冬,那么就返回一個可以響應(yīng)NSSet所有方法的代理集合
4免猾、還是沒找到,如果類方法accessInstanceVariablesDirectly返回YES囤热。那么按 _key猎提,_isKey,key旁蔼,iskey的順序搜索成員名
5锨苏、再沒找到,調(diào)用valueForUndefinedKey
KVC實(shí)現(xiàn)分析:
KVC運(yùn)用了isa-swizzing技術(shù)棺聊。isa-swizzing就是類型混合指針機(jī)制伞租。KVC通過isa-swizzing實(shí)現(xiàn)其內(nèi)部查找定位。isa指針(is kind of 的意思)指向維護(hù)分發(fā)表的對象的類限佩,該分發(fā)表實(shí)際上包含了指向?qū)崿F(xiàn)類中的方法的指針和其他數(shù)據(jù)葵诈。
例如:
[site setValue:@"sitename" forKey:@"name"];
//會被編譯器處理成
IMP method = objc_msg_loopup(site->isa,sel);
method(site,sel,@"sitename",@"name");```
每個類都有一張方法表,是一個hash表,值是還書指針I(yè)MP驯击,SEL的名稱就是查表時所用的鍵烁兰。
SEL數(shù)據(jù)類型:查找方法表時所用的鍵。定義成char*徊都,實(shí)質(zhì)上可以理解成int值沪斟。
IMP數(shù)據(jù)類型:他其實(shí)就是一個編譯器內(nèi)部實(shí)現(xiàn)時候的函數(shù)指針。當(dāng)Objective-C編譯器去處理實(shí)現(xiàn)一個方法的時候暇矫,就會指向一個IMP對象主之,這個對象是C語言表述的類型
### KVC的內(nèi)部機(jī)制:
一個對象在調(diào)用setValue的時候進(jìn)行了如下操作:
1. 根據(jù)方法名找到運(yùn)行方法的時候需要的環(huán)境參數(shù)
2. 他會從自己的isa指針結(jié)合環(huán)境參數(shù),找到具體的方法實(shí)現(xiàn)接口李根。
3. 再直接查找得來的具體的實(shí)現(xiàn)方法
## KVO模式
### KVO概念:鍵值觀察Key-Value-Observer就是觀察者模式
觀察者模式的定義:一個目標(biāo)對象管理所有依賴于它的觀察者對象槽奕,并在它自身的狀態(tài)改變時主動通知觀察者對象。這個主動通知通常是通過調(diào)用各觀察者對象所提供的接口方法來實(shí)現(xiàn)的房轿。觀察者模式較完美地將目標(biāo)對象與觀察者對象解耦
### KVO實(shí)現(xiàn)步驟:
1. 注冊監(jiān)聽
//keyPath就是要觀察的屬性值
//options給你觀察鍵值變化的選擇
//context方便傳輸你需要的數(shù)據(jù)
-(void)addObserver:(NSObject *)anObserver
forKeyPath:(NSString *)keyPath
options:(NSKeyValueObservingOptions)options
context:(void *)context
2. 實(shí)現(xiàn)監(jiān)聽
```//change里存儲了一些變化的數(shù)據(jù)粤攒,比如變化前的數(shù)據(jù),變化后的數(shù)據(jù)囱持;
//如果注冊時context不為空夯接,這里context就能接收到
-(void)observeValueForKeyPath:(NSString \*)keyPath
ofObject:(id)object
change:(NSDictionary \*)change
context:(void \*)context
- 移除監(jiān)聽
使用觀察者模式需要被觀察者的配合,當(dāng)被觀察者的狀態(tài)發(fā)生變化的時候通過事先定義好的接口(協(xié)議)通知觀察者纷妆。在KVO的使用中我們并不需要向被觀察者添加額外的代碼盔几,就能在被觀察的屬性變化的時候得到通知
KVO實(shí)現(xiàn)步驟分析:
- 當(dāng)類A的對象第一次被觀察的時候,系統(tǒng)會在運(yùn)行期動態(tài)創(chuàng)建類A的派生類掩幢。我們稱為B逊拍。
- 在派生類B中重寫類A的setter方法,B類在被重寫的setter方法中實(shí)現(xiàn)通知機(jī)制际邻。
- 類B重寫會 class方法芯丧,將自己偽裝成類A。類B還會重寫dealloc方法釋放資源枯怖。
- 系統(tǒng)將所有指向類A對象的isa指針指向類B的對象注整。
KVO同KVC一樣能曾,通過 isa-swizzling 技術(shù)來實(shí)現(xiàn)度硝。當(dāng)觀察者被注冊為一個對象的屬性的觀察對象的isa指針被修改,指向一個中間類寿冕,而不是在真實(shí)的類蕊程。其結(jié)果是,isa指針的值并不一定反映實(shí)例的實(shí)際類驼唱。
所以不能依靠isa指針來確定對象是否是一個類的成員藻茂。應(yīng)該使用class方法來確定對象實(shí)例的類
使用KVO的幾種方法:
- 使用了KVC
使用了KVC,如果有訪問器方法,則運(yùn)行時會在訪問器方法中調(diào)用will/didChangeValueForKey:方法辨赐;
沒用訪問器方法优俘,運(yùn)行時會在setValue:forKey方法中調(diào)用will/didChangeValueForKey:方法。 - 有訪問器方法
運(yùn)行時會重寫訪問器方法調(diào)用will/didChangeValueForKey:方法掀序。
因此帆焕,直接調(diào)用訪問器方法改變屬性值時,KVO也能監(jiān)聽到不恭。 - 顯示調(diào)用will/didChangeValueForKey:方法叶雹。