IOS中Key-Value Coding (KVC)的使用詳解
kvc,索引值編碼,是一個非正式的協議,它提供一種機制來間接訪問對象的屬性。直接存取對象是通過調用訪問器的方法實現,而kvc不需要調用訪問器的設定和擷取方法,可以直接存取對象的屬性。
下面介紹一下kvc的用法:
1、對屬性賦值
kvc是通過索引值對的方式對屬性設定值,提供了下面的方法,相當於訪問器中的set方法。value為要設定的值,key是字串,字串中內容為為屬性的名稱
- (void)setValue:(id)value forKey:(NSString *)key; - (void)setValue:(id)value forKeyPath:(NSString *)keyPath;
下面通過一個小例子講解一下通過訪問器和kvc對屬性賦值的代碼實現。
假設Student類中有一個name屬性,直接對name賦值的方式為:
Student *stu = [[Student alloc] init]; stu.name = @jerehedu;
通過kvo對name進行賦值:
Student *stu = [[Student alloc] init]; [stu setValue:@jerehedu forKey:@name];
假設學生類中還有一個屬性為ClassInfo班級類的對象stuClass,在ClassInfo班級類中有個classNo班級號的屬性,下面通過直接的方式設定班級號:
stu.stuClass = [ClassInfo new]; stu.stuClass.classNo = 1;
通過kvc設定班級號:
stu.stuClass = [ClassInfo new]; [stu setValue:@(1) forKeyPath:@stuClass.classNo];
通過keyPath設定時,路徑由 xx.xx 表示;
value的值為OC對象,如果為基礎資料型別 (Elementary Data Type),需要進行裝箱,也就是封裝為OC對象;
2、擷取屬性的值
kvc提供了擷取對象屬性值的方法,相當於訪問器的get方法,取值的時候也是通過索引值對方式。
- (id)valueForKey:(NSString *)key; - (id)valueForKeyPath:(NSString *)keyPath;
下面通過一個小例子講解一下通過訪問器和kvc對屬性取值的代碼實現。
假設要擷取Student類中name的值,直接對name取值的方式為:
NSString *name = stu.name;
通過kvc取值的方式為:
NSString *name = [stu valueForKey:@name];
通過訪問器方法直接從Student類中取班級號:
int num = stu.stuClass.classNo;
通過kvc取Student類中中班級號:
int num = [[stu valueForKeyPath:@stuClass.classNo] intValue];
預設取到的值為OC對象,如果想得到基礎資料型別 (Elementary Data Type),需要進行拆箱操作。
3、key找不到時,處理異常
使用kvc時,如果代碼中的key值不存在,會拋出異常,可以在類中通過重寫它提供下面的這個方法來解決這個問題。
- (void)setValue:(id)value forUndefinedKey:(NSString *)key;
當key不存在時,會自動調用上面的這個方法,可以在這個方法中進行處理。
4、kvc的用法補充
kvc非常好用,可以簡化我們的代碼,除了可以不用通過訪問器方法,直接對屬性進行訪問外,還可以對對象中的屬性進行運算。
比如新添加一個Test測試類別,裡面有一個score分數的屬性,在Student類中有一個數組,數組中存放考試資訊(Test類對象),通過kvo可以直接得到數組中儲存的所有考試的平均成績、最好成績等。
通過kvo儲存考試數組資訊:
NSMutableArray *ary = [NSMutableArray array]; for (int i=0; i<5; i++) { Test *test = [[Test alloc] init]; [test setValue:@(100-10*i) forKey:@score]; [ary addObject:test]; } stu.testAry = ary;
在Student類中將考試資訊列印輸出:
NSLog(@show: testAry = %@ ,[self valueForKey:@testAry]); NSLog(@show: testAry.score = %@,[self.testAry valueForKey:@score] ); NSLog(@show: testAry.score = %@,[self.testAry valueForKeyPath:@score] ); NSLog(@show: 數組中總成績SUMscore = %@,[self.testAry valueForKeyPath:@@sum.score] ); NSLog(@show2: 數組中平均成績AVGscore = %@,[self.testAry valueForKeyPath:@@avg.score] ); NSLog(@show2: 數組中最大成績MAXscore = %@,[self.testAry valueForKeyPath:@@max.score] ); NSLog(@show2: 數組中最小成績MINscore = %@,[self.testAry valueForKeyPath:@@min.score] );