1.KVC key value coding
我們一般是通過調(diào)用set方法
或屬性的點(diǎn)語法
來直接更改對象的狀態(tài)
诅岩,即對象的屬性值
疑枯,比如[stu setAge:10];`` stu.age = 9;
KVC
:它是一種間接更改對象狀態(tài)的方式
,其實(shí)現(xiàn)方法是使用字符串來描述對象需要更改的屬性
棋恼。KVC中的基本調(diào)用包括valueForKey:
和setValue:ForKey:
骄酗,以字符串的形式向?qū)ο蟀l(fā)送消息
這里以Student和Card為例子
1.1valueForKey:
使用valueForKey:
獲取Student對象的name
NSString *name = student.name; // 直接訪問對象屬性
NSString *name = [student valueForKey:@"name"]; // KVC間接訪問對象屬性
valueForKey:首先查找以name
或isName
命名的getter方法
智润,如果不存在getter方法
,就在對象內(nèi)部查找名為_name
或name
的實(shí)例變量
注意贤徒,下列語句是合法
的
NSLog(@"age is %@", [student valueForKey:@"age"]);
NSLog中的%@輸出一個(gè)對象芹壕,但age是一個(gè)int值,而不是對象接奈,為什么會(huì)合理呢踢涌?原因如下:
使用valueForKey:時(shí),KVC會(huì)自動(dòng)將標(biāo)量值(int序宦、float睁壁、struct等)翻入NSNumber或NSValue中包裝成一個(gè)對象,然后返回
互捌。因此堡僻,KVC有自動(dòng)將標(biāo)量值包裝為對象的功能
。
1.2setValue:ForKey:
使用setValue:ForKey:
設(shè)置Student對象的name
student setName:@"solozyx"; // 直接修改對象屬性
student.name = @"solozyx"; // 直接修改對象屬性
[student setValue:@"solozyx" forKey:@"name"]; //KVC間接修改對象屬性
這個(gè)方法的工作方式和valueForKey:相同疫剃,首先查找setter方法
钉疫,例如setName:
,如果不存在setter方法
巢价,就在類中查找名為name
或者_name的實(shí)例變量
牲阁,然后為它賦值
使用setValue:ForKey:設(shè)置Student對象的age
[student setValue:[NSNumber numberWithInt:17] forKey:@"age"];
在設(shè)置一個(gè)標(biāo)量值時(shí)固阁,需要先將標(biāo)量值包裝成一個(gè)NSNumber或NSValue對象
1.3批處理
KVC可以對對象進(jìn)行批量更改
例如,同時(shí)獲取Student的age和name
NSArray *keys = [NSArray arrayWithObjects:@"name", @"age", nil];
NSDictionary *dict = [student dictionaryWithValuesForKeys:keys];
同時(shí)設(shè)置Student的age和name
NSArray *keys = [NSArray arrayWithObjects:@"name", @"age", nil];
NSArray *values = [NSArray arrayWithObjects:@"solozyx", [NSNumber numberWithInt:16], nil];
NSDictionary *dict = [NSDictionary dictionaryWithObjects:values forKeys:keys];
[student setValuesForKeysWithDictionary:dict];
1.4鍵路徑 key path
除了通過鍵設(shè)置值外城菊,KVC還支持鍵路徑
备燃,像文件系統(tǒng)路徑
一樣,其實(shí)就是屬性鏈?zhǔn)皆L問
比如凌唬,利用鍵路徑設(shè)置Student對象中Card對象的no
[student setValue:@"12345" forKeyPath:@"card.no"];
獲取Student對象中Card對象的no
[student valueForKeyPath:@"card.no"];
1.5數(shù)組的整體操作
如果向一個(gè)NSArray請求一個(gè)key并齐,KVC會(huì)查詢數(shù)組中的每個(gè)對象來查找這個(gè)key,然后將查詢結(jié)果打包到另一個(gè)數(shù)組中并返回
例如客税,Student里面有很多Book對象
獲取Student中所有Book的name
NSArray *names = [student.books valueForKeyPath:@"name"];
或者
NSArray *names = [student valueForKeyPath:@"books.name"];
注意:不能在鍵路徑中為數(shù)組添加索引
况褪,比如@"books[0].name"
1.6鍵路徑的運(yùn)算符
在鍵路徑中,可以引用一些運(yùn)算符來進(jìn)行一些運(yùn)算更耻,例如獲取一組值的平均值测垛、最小值、最大值或者總數(shù)
例如秧均,計(jì)算Student中Book的總數(shù)
NSNumber *count = [student.books valueForKeyPath:@"@count"];
或者
NSNumber *count = [student valueForKeyPath:@"books.@count"];
計(jì)算Student中所有Book的價(jià)錢(price)總和
NSNumber *sum = [student.books valueForKeyPath:@"@sum.price"];
或者
NSNumber *sum = [student valueForKeyPath:@"books.@sum.price"];
找出Student中Book的所有不同價(jià)位(排除相同價(jià)位)
NSArray *prices = [student.books valueForKeyPath:@"@distinctUnionOfObjects.price"];
或者
NSArray *prices = [student valueForKeyPath:@"books.@distinctUnionOfObjects.price"];
2.KVO key value observing
KVO是一種非常重要的機(jī)制食侮,它允許監(jiān)聽對象的屬性的變化
注冊監(jiān)聽器
- (void)addObserver:(NSObject *)anObserver
forKeyPath:(NSString *)keyPath
options:(NSKeyValueObservingOptions)options
context:(void *)context
anObserver :監(jiān)聽器對象
keyPath :監(jiān)聽的屬性
options :決定了當(dāng)屬性改變時(shí),要傳遞什么數(shù)據(jù)給監(jiān)聽器
監(jiān)聽器需要實(shí)現(xiàn)監(jiān)聽方法
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
keyPath :監(jiān)聽的屬性
object :誰的屬性改變了
change :屬性改變時(shí)傳遞過來的信息 取決于添加監(jiān)聽器時(shí)的options參數(shù)
移除監(jiān)聽器
-(void)removeObserver:(NSObject *)observer
forKeyPath:(NSString *)keyPath