原文?kvc kvo
KVC 概論
KVC(全稱 key-value-coding)即鍵值編碼。KVC 的操作方法由NSKeyValueCoding 非正式協(xié)議提供瞪醋,而NSObject(NSKeyValueCoding)就實現(xiàn)了這個協(xié)議,也就是說ObjC中幾乎所有的對象都支持 KVC 操作牍帚,它是一種不通過存取方法(Setter银伟、Getter),而通過屬性名稱字符串(key)間接訪問類屬性(實例變量)的機制并徘。
- (void)setValue:(nullable id)value forKey:(NSString *)key;
- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;
- (id)valueForKey:(NSString *)key;
- (nullable id)valueForKeyPath:(NSString *)keyPath;
KVC 實現(xiàn)原理
1遣钳、[item setValue:@"白開水ln簡書" forKey:@"name"];
1.首先去模型中查找有沒有 setName,若有麦乞,直接調(diào)用賦值 [self setName:@"白開水ln簡書"]耍贾。
2.若無,去模型中查找有沒有 name 屬性路幸,若有荐开,直接訪問屬性賦值 name = value。
3.若無简肴,再去模型中查找有沒有 _name 成員變量晃听,若有,直接訪問屬性賦值 _name = value砰识。
4.找不到能扒,就會直接報找不到的錯誤(valueForUndefinedKey:)。
2辫狼、[item setValuesForKeysWithDictionary:dict];
1.遍歷字典中所有 key初斑。
2.去模型中查找有沒有對應(yīng)的屬性。
LNPerson *person = [[LNPerson alloc] init];
person.dog = [[LNDog alloc] init];
[person.dog setValue:@"阿黃" forKey:@"name"];
[person setValue:@"旺財" forKeyPath:@"dog.name"];
NSLog(@"%@", person.dog.name);
區(qū)別:forKey: 和 forKeyPath:
1膨处、forKeyPath 包含了所有 forKey 的功能
2见秤、forKeyPath 進行內(nèi)部的點語法,層層訪問內(nèi)部的屬性
3、注意:key 值一定要在屬性中找到真椿,開發(fā)中最好使用forKeyPath鹃答。
KVO(Key-Value-Obersver)即鍵值監(jiān)聽,利用一個key來找到某個屬性并監(jiān)聽其屬性值得改變突硝,當(dāng)該屬性發(fā)生變化時测摔,會自動的通知觀察者,這比通知中心需要post通知來說,簡單了許多锋八。其實這也是一種典型的觀察者模式浙于。
KVO 使用步驟
給目標(biāo)對象的屬性添加觀察者
在回調(diào)方法中監(jiān)聽屬性的變化
移除觀察者
// 1.添加觀察者
[self.person addObserver:self forKeyPath:@"name" options: NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];}
- (void)dealloc{
// 2.移除觀察者
[self.person removeObserver:self forKeyPath:@"name"];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(LNPerson *)person change:(NSDictionary *)change context:(void *)context{
NSLog(@"%@------%@------%@", keyPath, change);
}
KVO 實現(xiàn)原理
當(dāng)一個類的屬性被觀察的時候,系統(tǒng)會通過runtime動態(tài)的創(chuàng)建一個該類的派生類挟纱,而且系統(tǒng)將這個類的isa指針指向了派生類路媚,從而實現(xiàn)了給監(jiān)聽的屬性賦值時調(diào)用的是派生類的setter方法。
還會在這個類的基類中重寫被觀察的屬性的setter方法樊销,重寫的setter方法會在調(diào)用原setter方法前后整慎,通知觀察對象值得改變
同時派生類還重寫了 class 方法以“欺騙”外部調(diào)用者它就是起初的那個類。
此外围苫,派生類還重寫了 dealloc 方法來釋放資源裤园。
KVO 實現(xiàn)原理
可以看到重寫的 setter 方法,給屬性賦值的前后分別調(diào)用了兩個方法剂府。
- (void)willChangeValueForKey:(NSString *)key;
- (void)didChangeValueForKey:(NSString *)key;
而- (void)didChangeValueForKey:(NSString *)key;會調(diào)用
- (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary *)change context:(nullable void *)context;