一、摘要
*1 KVO,即:Key-Value-Observing叨粘,它提供一種機(jī)制,當(dāng)指定的對(duì)象的屬性被修改后瘤睹,則觀察者就會(huì)接受到通知升敲。簡(jiǎn)單的說就是每次指定的被觀察的對(duì)象的屬性被修改后,KVO就會(huì)自動(dòng)通知相應(yīng)的觀察者了轰传。
*2 KVC是Key-Value-Coding的簡(jiǎn)稱驴党,它是一種可以直接通過字符串的名字(key)來訪問類屬性(實(shí)例變量)的機(jī)制。而不是通過調(diào)用Setter获茬、Getter方法訪問港庄。當(dāng)使用KVO倔既、Core Data、CocoaBindings鹏氧、AppleScript(Mac支持)時(shí)叉存,KVC是關(guān)鍵技術(shù)。
二度帮、作用
KVC作用一般是兩個(gè):字典轉(zhuǎn)模型 和 給私有的成員變量賦值
*1 字典轉(zhuǎn)模型
NSDictionary *dict=@{@"name":@"浩杰",@"age":@"18"};
Person *person=[Person new];
[person setValuesForKeysWithDictionary:dict];
NSLog(@"--%@---%@",person.name,person.age);
注意事項(xiàng):使用setValuesForKeysWithDictionary的時(shí)候歼捏,要保證字典的key的數(shù)量小于或者等于模型類,且key必須要和模型中的屬性名字相同笨篷,否則會(huì)出現(xiàn)錯(cuò)誤瞳秽。
*2 復(fù)雜的字典轉(zhuǎn)模型
如果一個(gè)模型類,其中一個(gè)屬性也是一個(gè)模型率翅,這種情況就需要給這個(gè)屬性傳入一個(gè)字典
NSDictionary *dict=@{@"name":@"浩杰",@"age":@"18",@"dog":@{@"name":@"tom",@"weight":@"10"}};
Person *person=[Person new];
[person setValuesForKeysWithDictionary:dict];
NSLog(@"----%@",person.dog);
// {
// name = tom;
// weight = 10;
// }
person.dog=[Dog new]; //必須加這句話练俐,不加之前,查看打印結(jié)果會(huì)看到person.dog類型是字典冕臭;加之后打印結(jié)果是Dog
NSLog(@"----%@",person.dog);
//<Dog: 0x7fef69c01de0>
[person.dog setValuesForKeysWithDictionary:dict[@"dog"]];
注意事項(xiàng):當(dāng)給person對(duì)象發(fā)送setValuesForKeysWithDictionary消息的時(shí)候腺晾,實(shí)際上此時(shí)它的dog屬性指向一個(gè)字典,而不是Dog類的對(duì)象
*3 給私有的成員變量賦值
如果是在.h中定義了某個(gè)屬性辜贵,這是暴露給外界悯蝉,可以被訪問(public或者protect類型);如果是在.m中定義了某個(gè)屬性托慨,用KVC則同樣可以進(jìn)行賦值和取值操作鼻由。
Person *person=[Person new];
[person setValue:@"1.85" forKey:@"height"];
NSLog(@"--%@",[person valueForKey:@"height"]);
注意:屬性height是在.m文件中定義的; value的值一定是對(duì)象厚棵,所以即使person的私有成員變量是int類型的蕉世,但是setValue的時(shí)候要將其賦值為對(duì)象類型的。在進(jìn)行取值的時(shí)候也是一樣取出對(duì)象婆硬,使用NSNumber狠轻。
KVO 主要用來監(jiān)聽某個(gè)對(duì)象的某個(gè)屬性的變化,當(dāng)發(fā)生變化的時(shí)候彬犯,觀察者會(huì)調(diào)用對(duì)應(yīng)的函數(shù)向楼,實(shí)現(xiàn)對(duì)應(yīng)的功能
Person *person=[Person new];
[person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew |NSKeyValueObservingOptionOld context:nil];
//當(dāng)person的name發(fā)生變化的時(shí)候,self就會(huì)執(zhí)行下面的函數(shù)躏嚎,在該函數(shù)中實(shí)現(xiàn)相應(yīng)功能即可
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
}
注意事項(xiàng):
//如果進(jìn)行了addobserver操作蜜自,那么就要進(jìn)行相應(yīng)的removeObserver操作。這是因?yàn)椋篴ddobserver操作卢佣,會(huì)在通知中心注冊(cè)監(jiān)聽者(這里是self)重荠,當(dāng)self這個(gè)對(duì)象銷毀后,如果沒有removeObserver虚茶,那么當(dāng)屬性改變時(shí)候戈鲁,仍然會(huì)給self這個(gè)已經(jīng)銷毀的對(duì)象發(fā)送屬性改變的消息仇参,因?yàn)樵谕ㄖ行闹校呀?jīng)銷毀的對(duì)象并沒有撤銷注冊(cè)
-(void)dealloc{
[self.person removeObserver:self forKeyPath:@"name"];
}