KVC 和 KVO
- KVC 鍵值對編碼绽慈,簡單來說恨旱,就是控制一切鍵值對,作用分為 setter 和 getter方法
- setter用法
- 1.賦予單個對象的值
[p setValue:@(668.0) forKey:@"money"];
- 2.賦予對象內部屬性值坝疼,間接多層賦值搜贤, setValue:forKeyPath: 可以給對象的間接屬性賦值. 多層賦值 建議一直使用
[p setValue:@(110) forKeyPath:@"dog.price"];
- 3.給私有成員賦值,私有成員钝凶,只能在那個類里使用仪芒,都可以用set方法賦值,
[p setValue:@"lnj" forKey:@"_name"];
- 4.字典轉模型
[p setValuesForKeysWithDictionary:dict];
- 注意點:
1耕陷,模型需要和字典掂名,個數(shù),類型哟沫,名字對應饺蔑,
2. 只能對模型的當前屬性,進行轉換南用,如果模型里還有其他的對象的話,轉換時不會報錯,用到時會崩掉裹虫。
-
getter 方法
- 1.獲取單個對象的值
NSString *name = [p valueForKey:@"name"];
- 2.獲得深層對象的值
NSString *dogName = [p valueForKeyPath:@"dog.name"];
- 3.模型轉字典 注意模型和字典需要對應
NSDictionary *dict = [p dictionaryWithValuesForKeys:@[@"name", @"money"]];
- 4.獲取數(shù)組中對象的值 一個數(shù)組里存儲的是對象肿嘲,對象的值可以通過KVC取出來放到另一個數(shù)組中,
NSArray *arr = @[p1, p2, p3];
// 如果數(shù)組中的元素都是同一種類型的數(shù)據(jù), 可以使用KVC獲取數(shù)組中所有對象的某個屬性的值
NSArray *res = [arr valueForKeyPath:@"name"];
- 5.運算符 上面取值的時候筑公,可以進行運算雳窟,
id res1 = [arr valueForKeyPath:@"@avg.money"]
-
KVO 鍵值對 觀察 意思就是觀察鍵值對的改變
- 1.給某個對象的值,添加觀察者匣屡,一旦它的值發(fā)生改變封救,會通知你設置的接收對象,類似代理 和 通知
/* 第一個參數(shù): 告訴系統(tǒng)哪個對象監(jiān)聽 第二個參數(shù): 監(jiān)聽當前對象的哪個屬性 第三個參數(shù): 監(jiān)聽到屬性改變之后, 傳遞什么值 第四個參數(shù): 需要傳遞的參數(shù) (這個參數(shù)不是傳遞給屬性的) */ // 給p這個對象添加一個監(jiān)聽 , 監(jiān)聽p對象的age屬性的改變, 只要age屬性改變就通知self [p addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
- 2.一旦添加了觀察者,那么在對象釋放之前一定要移除觀察者對對象值的監(jiān)聽
[p removeObserver:self forKeyPath:@"age"];
- 3.值發(fā)生改變的同時捣作,會調用以下方法
// 只要監(jiān)聽到屬性的改變就會調用
// keyPath: 被監(jiān)聽的屬性名稱
// object : 被監(jiān)聽的對象
// context: 注冊監(jiān)聽的時候傳入的值
- (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary *)change context:(nullable void *)context
{
NSLog(@"keyPath = %@, object = %@ , change = %@, context = %@", keyPath, object, change, context);
}
####KVO的原理
- 只要給一個對象注冊一個監(jiān)聽, 那么在運行時, 系統(tǒng)就會自動給該對象生成一個子類對象,
并且重寫自動生成的子類對象的被監(jiān)聽屬性的set方法, 然后在set方法中通知監(jiān)聽者
NSKVONotifying_Person 就是生成的子類