1 .KVC(Key Value Coding)
鍵值編碼方法,可以給屬性,甚至是私有屬性進行賦值和取值,簡化字典—>模型,以及模型—>字典的轉(zhuǎn)變;
(1) 對屬性進行賦值,類似于setter方法;以及字典—>模型;
<1> 對模型中簡單屬性賦值;
GMQPerson *p = [[GXQPerson alloc] init];
p.dog = [[GMQDog alloc] init];
[p setValue:@"GMQ"forKey:@"name”]; —>keyPath的功能比key的功能更強大
[p.dog setValue:@"wangcai" forKey:@"name"];
<2> 對復雜嵌套的屬性賦值,
[p setValue:@"wangcai" forKey:@"dog.name"];//注意:? 錯誤寫法!!!人對象中沒有dog.name這個屬性
[p.dog setValue:@"wangcai" forKeyPath:@“name"];//正確
[p setValue:@"wangcai" forKeyPath:@"dog.name"];// 按照路徑找到相應的屬性
<3>核心功能,可以對私有成員變量進行賦值;
[p setValue:@"1.79" forKeyPath:@"_height”];// 經(jīng)測試,這里既可以寫成_height,也可以寫成height;
<4> 簡化字典—>模型的操作;
NSDictionary *dict = @{
@"name" : @"GMQ",
@"age" : @"23",
@"no" : @"123456"
};
這一條語句相當于下面的幾句,將字典中的每一個鍵值對拆開,分別賦值給模型中的每一個屬性;需要注意的是如果字典中有一個key是模型中沒有的屬性,那么用這條語句運行時就會報錯。
[p setValuesForKeysWithDictionary:dict];;
[p setValue:@"GMQ" forKey:@"name"];
[p setValue:@"23" forKey:@"age"];
[p setValue:@"123456" forKey:@"no"];//no是字典中的key值,但是在模型中沒有這個屬性,會報錯。
(2) 對屬性進行取值,類似于getter方法;以及模型—>字典;
<1> 對模型中簡單屬性取值;
[p valueForKeyPath:@"name”];
<2> 對復雜嵌套的屬性取值,
[p valueForKeyPath:@“dog.name”];
<3>核心功能,可以對私有成員變量進行取值;
NSLog(@"%@",[p valueForKeyPath:@"_height"]);
<4> 簡化模型—>字典的操作;
GXQPerson*p = [[GXQPersonalloc]init];
p.name=@"jack";
p.age=20;
NSDictionary*dict = [p dictionaryWithValuesForKeys:@[@"name",@"age"]];
還有一些其他的方法:
NSArray*arr =@[p, p1, p2];
NSArray*names = [arr valueForKeyPath:@"name”];// 返回一個所有的name屬性的值組成的數(shù)組;
NSLog(@"%@",[arr valueForKeyPath:@"@avg.age"]);// 引號內(nèi)的@是一個運算符,這里算出的是數(shù)組中所有元素的年齡屬性的值的平均值;
[p setValue:<#(nullable id)#>forUndefinedKey:<#(nonnull NSString *)#>];// 這是系統(tǒng)才能調(diào)用的方法;
2 .KVO(Key Value Observing)
鍵值監(jiān)聽/鍵值觀察;可以監(jiān)聽模型屬性值的變化;只要模型屬性值一有變化,就會調(diào)用監(jiān)視方法,屬于即時調(diào)用;還有一點,在被監(jiān)視對象將要銷毀前,一定要移除監(jiān)聽,否則程序會報錯。
GMQPerson*p = [[GMQ Personalloc]init];
p.name=@"GMQ";
[p addObserver:self forKeyPath:@"name" options:NSKeyValueObservingNew | NSKeyValueObservingOld context:@"haha"];
// 給p添加一個監(jiān)聽器,self代表控制器,也可以是其他類的對象,如果是其他類,則一定要把監(jiān)視方法寫到那個類中;
// keyPath 表示監(jiān)聽的是哪個屬性;
//?options是個枚舉值,根據(jù)options傳入的數(shù)據(jù),會在監(jiān)聽方法的change字典中賦予相應的值;
p.name=@"xiaoming”;// 即時調(diào)用,因此會調(diào)用兩次監(jiān)聽方法;
p.name=@"xiaohong";
[p removeObserver:self forKeyPath:@"name”];// 在被監(jiān)聽的對象銷毀前,一定移除監(jiān)聽,否則運行會報錯;
}
// 下面是監(jiān)聽的方法,每次屬性值改變都會調(diào)用,即使賦予的值相同,也會調(diào)用
- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void
*)context
{
// keyPath:是監(jiān)聽的哪個屬性的變化;
// object:表示的是監(jiān)聽的哪個對象的屬性改變了
//change是個字典,根據(jù)上面options傳入的數(shù)據(jù),給對應的key賦值
//context:添加監(jiān)聽器中傳入的參數(shù)
//??? NSLog(@"%@,%@,%@,%@",keyPath,object,change,context);
NSLog(@"%@",change[NSKeyValueChangeNewKey]);//取出字典中key為NSKeyValueChangeNewKey的值,表示更改后的值;對應
NSKeyValueObservingOptionNew;
NSLog(@"%@",change[NSKeyValueChangeOldKey]);// 取出字典中key為NSKeyValueChangeOldKey的值,表示更改后的值;對應
NSKeyValueObservingOptionOld;
}
3.KVC和KVO的區(qū)別和聯(lián)系:
KVC的主要作用:給模型中的屬性賦值和取值
KVO的主要作用:監(jiān)聽模型中屬性值的改變
KVC是路徑訪問的規(guī)范,KVO則是觀察某個變量的變化過程
KVC/KVO類似于代理,通知,都是一種通訊方法。