一蔓挖、KVC
通過關鍵字徊都,訪問屬性及成員變量茧痒。
1.kvc當調(diào)用setValue:屬性值 forKey:@”name“的代碼時罕偎,底層的執(zhí)行機制(順序)如下:
①.set方法:set<Key> (注意降淮,通過屬性自動合成的set方法也算)
(BOOL)accessInstanceVariablesDirectly方法有沒有返回YES阶淘,默認該方法會返回YES角溃,繼續(xù)向下尋找是否有滿足的成員變量睬愤。
(如果你重寫了該方法讓其返回NO的話淆九,那么在這一步KVC會直接執(zhí)行⑤setValue:forUNdefinedKey:方法蚂且,不過一般開發(fā)者不會這么做配猫。所以,如果想讓自己的類禁用kvc杏死,可以用此方法返回NO泵肄,不過記得屬性會自動合成set方法)
②.成員變量:
_<key>成員變量佳遣,
_is<Key>成員變量,
<key>成員變量凡伊,
is<Key>成員變量零渐,
③.執(zhí)行該對象的setValue:forUNdefinedKey:方法,默認是拋出異常系忙。
- 當調(diào)用valueForKey:@"name"時诵盼,執(zhí)行機制(順序)如下:
①.訪問器方法:get<Key>,<key> 银还,is<Key>
②.成員變量:
_<key>成員變量风宁,
_is<Key>成員變量,
<key>成員變量蛹疯,
is<Key>成員變量戒财。
所以KVC支持實例變量。
- KVC的keyPath中的集合運算符
@avg捺弦、@sum饮寞、@max、@min列吼、@count
必須用在集合對象或集合屬性上幽崩,@"@sum.age"或 @"集合屬性.@max.age"。比如Person類中有個age屬性寞钥,
NSArray *array = [NSArray arrayWithObjects:p1, p2, p3, nil];
NSInteger max = [[array valueForKeyPath:@"@max.age"] integerValue];
二慌申、KVO
1. 基本使用
KVO是一種機制,對象可以指定一個觀察者理郑,來觀察它的某個屬性蹄溉,當該屬性發(fā)生改變時,觀察者會收到通知您炉,來執(zhí)行相應的操作柒爵。
只需兩部即可完成:
步驟一、 添加鍵值觀察
[self.person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:@"Person Name"];
參數(shù):
- 觀察者邻吭,負責處理監(jiān)聽事件的對象
- 觀察的屬性
- 觀察的選項
- 上下文
步驟二餐弱、observer中需要實現(xiàn)一下方法:
// 所有的 kvo 監(jiān)聽到事件宴霸,都會調(diào)用此方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
參數(shù):
- 觀察的屬性
- 觀察的對象
- change 屬性變化字典(新/舊)
- 上下文囱晴,與監(jiān)聽的時候傳遞的一致
2. 如何手動觸發(fā)KVO
鍵值觀察通知依賴于 NSObject 的兩個方法: willChangeValueForKey:
和 didChangevlueForKey:
。所以我們只需要直接調(diào)用這兩個方法瓢谢,即可手動觸發(fā)KVO畸写。
3. 手動實現(xiàn)實例變量支持KVO
如果將一個對象設定成屬性,這個屬性是自動支持KVO的,如果這個對象是一個實例變量,那么氓扛,這個KVO是需要我們自己來實現(xiàn)的枯芬。
需要兩個步驟:
步驟一:實現(xiàn)set方法论笔,在set方法中添加手動觸發(fā)KVO需要的兩個方法。
-(void)setName:(NSString *)name
{
[self willChangeValueForKey:@"name"];
_name = name;
[self didChangeValueForKey:@"name"];
}
步驟二:在該對象中實現(xiàn)automaticallyNotifiesObserversForKey方法千所,指定該key值為非自動監(jiān)聽
+(BOOL)automaticallyNotifiesObserversForKey:(NSString *)key
{
if ([key isEqualToString:@"name"]) {
return NO;
}
return YES;
}
4. KVO的實現(xiàn)原理
當對象設置了觀察者時狂魔,會生成一個新類,這個類繼承自該對象的原類淫痰,這個新類會重寫set方法最楷,在set方法中增加KVO所依賴的兩個方法willChangeValueForKey:
和 didChangevlueForKey:
方法,然后該對象的isa指針指向新生成的類(isa 混寫(isa-swizzling))待错。