KVO可以用于監(jiān)聽某個對象屬性值得改變滋尉。
_NSSet*ValueAndNotify的內(nèi)部實(shí)現(xiàn):
調(diào)用willChangeValueForKey:
調(diào)用原來的setter實(shí)現(xiàn)
調(diào)用didChangeValueForKey:
在didChangeValueForKey:內(nèi)部會調(diào)用observe的observeValueForKeyPath:ofObject:change:context:方法
KVO的本質(zhì)是什么?
利用RuntimeAPI動態(tài)生成一個子類钧汹,并且讓instance對象的isa指向這個全新的子類哑舒;
當(dāng)修改instance對象的屬性時,會調(diào)用Foundation的_NSSet*ValueAndNotify函數(shù);
Runtime動態(tài)生成子類重寫方法吮螺。
- (void)printMethodNamesOfClass:(Class)cls
{
unsigned int count;
// 獲得方法數(shù)組
Method *methodList = class_copyMethodList(cls, &count);
// 存儲方法名
NSMutableArray *methodNames = [NSMutableArray array];
// 遍歷所有的方法
for (int i = 0; i < count; i++) {
// 獲得方法
Method method = methodList[i];
// 獲得方法名
NSString *methodName = NSStringFromSelector(method_getName(method));
// 拼接方法名
[methodNames addObject:methodName];
}
// 釋放
free(methodList);
// 打印方法名
NSLog(@"%@ %@", cls, methodNames);
}
//注意:此處調(diào)用必須使用Runtime底層獲取類對象的方法,因?yàn)镽untime自動生成
的類中重寫了class方法帕翻,調(diào)用[self.person1 class]不能夠獲取到真正的類對象
[self printMethodNamesOfClass:object_getClass(self.person1)];
NSKVONotifying_MJPerson (
"setAge:",
class,
dealloc,
"_isKVOA"
)
setAge 方法 : KVO 實(shí)現(xiàn)的主要方法
class 方法:屏蔽內(nèi)部實(shí)現(xiàn)鸠补,隱藏了Runtime自動生成子類的存在。
dealloc 方法 :當(dāng)對象釋放時嘀掸,將Runtime生成的子類也進(jìn)行釋放紫岩。
_isKVOA 方法 : 說明自己是kvo類。
直接修改成員變量的值睬塌,是不會觸發(fā)KVO的監(jiān)聽方法的泉蝌。