KVC
kvc提供了一種在運行時而非編譯時動態(tài)訪問對象屬性與成員變量的方式,該方法不需要調(diào)用get/set方法
OC中訪問變量的方式
- _name 直接訪問
- self.name 利用屬性訪問
- [self setValue:@"" forKey:@""] KVC
[self valueForKey:@"someKey"];
查找過程:
1.查找對象是否帶有someKey這個方法
2.查找對象是否代用someKey這個實例變量(iVar)
3.調(diào)用 -(id)valueForUndefinedKey
4.拋出NSUndefinedKeyException異常
KVC內(nèi)部實現(xiàn)
一個對象在調(diào)用setValue時
1.根據(jù)方法名找到運行方法的時候所需要的環(huán)境參數(shù)
2.從自己的isa指針結(jié)合環(huán)境參數(shù),找到具體的方法實現(xiàn)的接口,isa指針,指向維護分發(fā)表的對象的類,該分發(fā)表實際上包含了指向?qū)崿F(xiàn)類中的方法的指針
3.直接查找得來的具體的方法實現(xiàn)
@interface LBKVC : NSObject {
NSString *firstName;
}
@property (nonatomic, strong) NSString *lastName;
@end
[_kvc setValue:@"dog" forKey:@"lastName"]; // 屬性 會觸發(fā) set 方法
[_kvc setValue:@"cat" forKey:@"firstName"]; // 成員變量 沒有set方法
KVO
KVO主要用來解耦
在上面介紹的KVC機制上加上KVO的自動觀察消息通知機制就水到渠成了。
*KVO是基于runtime機制實現(xiàn)的
*當某個類的屬性對象被觀察時,系統(tǒng)會在運行期動態(tài)地創(chuàng)建該類的一個派生類,在這個派生類中重寫基類中任何被觀察屬性的setter方法。派生類在被重寫的setter方法內(nèi)實現(xiàn)真正的通知機制
*如果原來類為Person,那么生成的派生類名為NSKVONotifying_Person
*每個類對象中都有一個isa指針指向當前類,當一個類對象被觀察,那么系統(tǒng)會偷偷將isa指針指向動態(tài)生成的派生類,從而在給被監(jiān)控屬性賦值時執(zhí)行的是派生類的setter方法
*鍵值觀察通知 依賴于NSObject的兩個方法 willChangeValueForKey 和 didChangeValueForKey 。在一個被觀察屬性發(fā)生改變之前,willChangeValueForKey 一定會被調(diào)用,這樣就會記錄舊的值,而當值改變后,didChangeValueForKey 會被調(diào)用,繼而observeValueForKey:ofObject:change:context:也會被調(diào)用

// 手動觸發(fā)
[self willChangeValueForKey:@"name"];
[self didChangeValueForKey:@"name"];