kvc,鍵值編碼,是一個非正式的協議,它提供一種機制來間接訪問對象的屬性。直接訪問對象是通過調用訪問器的方法實現,而kvc不需要調用訪問器的設置和獲取方法,可以直接訪問對象的屬性。
下面介紹一下kvc的用法:
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對象,如果為基本數據類型,需要進行裝箱,也就是包裝為OC對象;
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對象,如果想得到基本數據類型,需要進行拆箱操作。
使用kvc時,如果代碼中的key值不存在,會拋出異常,可以在類中通過重寫它提供下面的這個方法來解決這個問題。
- (void)setValue:(id)value forUndefinedKey:(NSString *)key;
當key不存在時,會自動調用上面的這個方法,可以在這個方法中進行處理。
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] );