使用時小技巧
一、自動開關(guān)automaticallyNotifiesObserversForKey:,如果返回NO則對應(yīng)的字段監(jiān)聽就需要手動觸發(fā)了族扰,在set方法中把變量的修改用willChangeValueForKey:和didChangeValueForKey:包裹
- (void)setNick:(NSString *)nick{
[self willChangeValueForKey:@"nick"];
_nick = nick;
[self didChangeValueForKey:@"nick"];
}
二、如果想對監(jiān)聽key做一個轉(zhuǎn)換,例如想監(jiān)聽keyA诅需,實際內(nèi)容需要監(jiān)聽B和C兩個屬性的變化,通過keyPathForValuesAffectingValueForKey:進(jìn)行轉(zhuǎn)換即可
+ (NSSet<NSString *> *)keyPathsForValuesAffectingValueForKey:(NSString *)key{
NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key];
if ([key isEqualToString:@"downloadProgress"]) {
NSArray *affectingKeys = @[@"totalData", @"writtenData"];
keyPaths = [keyPaths setByAddingObjectsFromArray:affectingKeys];
}
return keyPaths;
}
三荧库、對于數(shù)組的觀察需要利用kvc的技術(shù)來進(jìn)行
//有這樣一個對象堰塌,有一個NSMutableArray的屬性
@interface LGPerson : NSObject
@property (nonatomic, strong) NSMutableArray *dateArray;
@end
//監(jiān)聽其屬性變化
[self.person addObserver:self forKeyPath:@"dateArray" options:(NSKeyValueObservingOptionNew) context:NULL];
//只有通過kvc的方法修改屬性才能觸發(fā)kvo的監(jiān)聽回調(diào)
[[self.person mutableArrayValueForKey:@"dateArray"] addObject:@"1"];
KVO的原理
1.動態(tài)生成子類NSKVONotifiy_A,修改當(dāng)前對象的isa分衫,這樣才進(jìn)行消息轉(zhuǎn)發(fā)時才會進(jìn)到子類的方法列表中來场刑。
2.動態(tài)給子類添加setter方法,class方法蚪战,dealloc方法牵现,_isKVOA方法。setter方法是為了能攔截賦值過程通知給觀察者邀桑,class方法是為了調(diào)用[object class]方法時不對外暴露子類的信息瞎疼,dealloc方法是為了在對象釋放時把isa指回來,_isKVOA方法是為了標(biāo)記當(dāng)前類的是用于kvo的壁畸。
3.在動態(tài)生成的setter方法中把消息轉(zhuǎn)發(fā)給父類贼急,調(diào)用父類的setter方法,并通知觀察者屬性變化捏萍。
具體過程推薦學(xué)習(xí)iOS-底層原理 23:KVO 底層原理