鍵值編碼

編譯器會(huì)自動(dòng)生成setter和getter的訪問(wèn)器方法,但是這樣是直接調(diào)用訪問(wèn)器方法,還有一種以間接的方法進(jìn)行修改對(duì)象的屬性的方法,這種方法使用的就是鍵值編碼。

//   這樣的就是訪問(wèn) 訪問(wèn)方法選擇器的方法,直接使用setter方法進(jìn)行方法的賦值
    [self.view setBackgroundColor:[UIColor redColor]];
//   這樣就是使用鍵值方法,對(duì)對(duì)象的某個(gè)屬性進(jìn)行間接賦值的方法
    [self.view setValue:[UIColor redColor] forKey:@"backgroundColor"];
//forKeyPath是關(guān)鍵路徑,前面的屬性是相對(duì)于接受者的,下一級(jí)的屬性是相對(duì)于前面的屬性的,這個(gè)例子view是相對(duì)于self的,backgroundView是相對(duì)于view的
    [self setValue:[UIColor redColor] forKeyPath:@"view.backgroundColor"];
//   獲取制定key的值
  id value =  [self.view valueForKey:@"backgroundColor"];
/**
 如果valueforkey的key不存在,會(huì)調(diào)用這個(gè)方法,但是必須得在子類中,進(jìn)行重寫,如果在其他類中實(shí)現(xiàn),不會(huì)調(diào)用這個(gè)方法,否則會(huì)奔潰
例如上面的方法,必須在self.view方法中的view中進(jìn)行重寫這個(gè)方法
 @param key 制定的key值
 @return 返回的值
 */
-(id)valueForUndefinedKey:(NSString *)key{
    return @"";
}
//    返回的值是個(gè)字典,參數(shù)為為字符串的數(shù)組,調(diào)用這個(gè)方法會(huì)對(duì)參數(shù)的數(shù)組中key值進(jìn)行valueForKey操作,返回的字典就是一個(gè)key和keyvalue的值,組成的字典
 NSDictionary * dict =   [self dictionaryWithValuesForKeys:@[@"view",@"viewIfLoaded",@"parentViewController",@"presentedViewController",@"presentingViewController"]];
//    setter方法
//給消息接受者指定的key設(shè)置指定的值
    [self.view setValue:[UIColor yellowColor] forKey:@"backgroundColor"];
    
    [self setValue:[UIColor orangeColor] forKeyPath:@"view.backgroundColor"];
    
    //setValuesForKeysWithDictionary底層是對(duì)字典中的key進(jìn)行遍歷,對(duì)每個(gè)key調(diào)用setValue:forKeyPath:方法,在字典中的key不能使用關(guān)鍵路徑的形式
    [self.view setValuesForKeysWithDictionary:@{@"backgroundColor":[UIColor purpleColor],@"alpha":[NSNumber numberWithFloat:0.5]}];
@property (nonatomic,assign) int num;

//    當(dāng)給非對(duì)象的屬性key進(jìn)行輔助nil對(duì)象的時(shí)候,會(huì)調(diào)用setNilValueForKey方法,可以在里面進(jìn)行修改設(shè)置
    [self setValue:nil forKeyPath:@"num"];
//對(duì)非對(duì)象的屬性進(jìn)行賦值為nil的時(shí)候會(huì)調(diào)用
-(void)setNilValueForKey:(NSString *)key{
    if ([key isEqualToString:@"num"]) {
        _num = 1;
    }
}

訪問(wèn)集合對(duì)象的屬性的方法

@property (nonatomic,strong) NSArray * numArray;

  self.numArray = @[@"1",@"2",@"3",@"4",@"10"];
  NSMutableArray * array =   [self mutableArrayValueForKey:@"numArray"];
屏幕快照 2019-02-14 上午11.45.54.png

使用集合運(yùn)算符進(jìn)行操作

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface Person : NSObject
@property (nonatomic,copy)NSString * name;
@property (nonatomic,strong) NSNumber * age;
@property (nonatomic,strong) NSDate * date;

@end
//    使用關(guān)鍵路徑的getter方法時(shí)候,在關(guān)鍵路徑中嵌入集合運(yùn)算符例如在集合運(yùn)算符前加上@標(biāo)志,在集合運(yùn)算符前面的部分為左鍵,代表的是消息的接受者的操作集合,集合運(yùn)算符后面的部分,成為右鍵,表示的是指定集合操作符處理集合里面的指定的屬性
  NSNumber * string =   [self valueForKeyPath:@"numArray.@sum.floatValue"];
  NSNumber * string1 =  [self.numArray valueForKeyPath:@"@sum.floatValue"];
    Person * p = [[Person alloc]init];
    self.persongArray = [NSMutableArray array];
    p.age = @20;
    p.name = @"小明";
    [self.persongArray addObject:p];
    
    Person * p1 = [[Person alloc]init];
    p1.age = @22;
    p1.name = @"小王";
    [self.persongArray addObject:p1];
    //    求和操作
   id sumAge = [self valueForKeyPath:@"persongArray.@sum.age"];

//    求平均值操作
  NSNumber * avgAge =  [self valueForKeyPath:@"persongArray.@avg.age"];
//    計(jì)算操作沒(méi)有左鍵的方式,因?yàn)榻邮苷呔褪莻€(gè)集合了
  NSNumber * count =  [self.persongArray valueForKeyPath:@"@count"];
//    計(jì)算個(gè)數(shù)的操作符,還有左鍵的方式,左鍵代表的消息接受者的操作集合對(duì)象
    NSNumber * count1 = [self valueForKeyPath:@"persongArray.@count"];
//   取集合中的最大值
   NSNumber * maxAge = [self valueForKeyPath:@"persongArray.@max.age"];
//    取集合中的最小值
    NSNumber * minAge = [self valueForKeyPath:@"persongArray.@min.age"];
//獲取一個(gè)數(shù)組集合,去掉重復(fù)內(nèi)容的數(shù)組
 NSArray * distinctAgeArray =   [self valueForKeyPath:@"persongArray.@distinctUnionOfObjects.age"];
    //獲取一個(gè)數(shù)組集合,沒(méi)有去掉重復(fù)內(nèi)容的數(shù)組
   NSArray * ageArray = [self valueForKeyPath:@"persongArray.@unionOfObjects.age"];

數(shù)組嵌套數(shù)組的操作

@property (nonatomic,strong) NSMutableArray * arrayOfArray;
@property (nonatomic,strong) NSMutableArray * myArray;
 self.arrayOfArray = [NSMutableArray array];
    [self.arrayOfArray addObject:self.persongArray];
    Person * p3 = [[Person alloc]init];
    p3.age = @23;
    p3.name = @"小許";
    self.myArray = [NSMutableArray array];
    [self.myArray addObject:p3];
    
    [self.arrayOfArray addObject:self.myArray];
//    從嵌套的數(shù)組中,取出右鍵指定的屬性,組成一個(gè)新的數(shù)組,這個(gè)不會(huì)去掉重復(fù)的內(nèi)容
   NSArray * arrayOfArray = [self valueForKeyPath:@"arrayOfArray.@unionOfArrays.age"];
    //    從嵌套的數(shù)組中,取出右鍵指定的屬性,組成一個(gè)新的數(shù)組,這個(gè)會(huì)去掉重復(fù)的內(nèi)容
    NSArray * distinctArrayOfArray = [self valueForKeyPath:@"arrayOfArray.@distinctUnionOfArrays.age"];

@distinctUnionOfSets
指定@distinctUnionOfSets運(yùn)算符時(shí),valueForKeyPath:創(chuàng)建并返回一個(gè)NSSet對(duì)象,該對(duì)象包含與右鍵路徑指定的屬性對(duì)應(yīng)的所有集合的組合的不同對(duì)象。

此運(yùn)算符的行為與此類似@distinctUnionOfArrays,只是它需要一個(gè)NSSet包含NSSet對(duì)象實(shí)例而不是NSArray實(shí)例實(shí)例的NSArray實(shí)例。此外,它返回一個(gè)NSSet實(shí)例。假設(shè)示例數(shù)據(jù)已存儲(chǔ)在集合而不是數(shù)組中,示例調(diào)用和結(jié)果與顯示的相同@distinctUnionOfArrays。

表示非對(duì)象值

//創(chuàng)建一個(gè)結(jié)構(gòu)體
struct ThreeFloat {
    float a,b,c;
};

//增加一個(gè)屬性
@property (nonatomic,assign) struct ThreeFloat threeFloat;

//    給結(jié)構(gòu)體賦值
   struct ThreeFloat threeFloat = {1.,2.,4.};
//    轉(zhuǎn)為nsvalue對(duì)象
  NSValue * threeValue =  [NSValue value:&threeFloat withObjCType:@encode(struct ThreeFloat)];
//    使用kvc進(jìn)行賦值操作
    [self setValue:threeValue forKey:@"threeFloat"];

驗(yàn)證屬性

   NSError * error;
 BOOL isBool =   [self validateValue:&threeValue forKey:@"threeFloat" error:&error];

如果當(dāng)其中一個(gè)鍵值編碼的訪問(wèn)器方法無(wú)法找到屬性的訪問(wèn)器時(shí)候,可以看這個(gè)類是否可以使用實(shí)例變量的方式

    BOOL isbool =  [[self class] accessInstanceVariablesDirectly];

使用鍵值編碼協(xié)議當(dāng)中的方法來(lái)獲取集合屬性的操作

@property (nonatomic,strong) NSMutableArray * nameArray;

//    初始化一個(gè)數(shù)組
    self.nameArray = [NSMutableArray arrayWithArray:@[@"小明",@"小李",@"小王"]];
    
//    調(diào)用數(shù)組的個(gè)數(shù)
  NSInteger nameCount =  [self countOfNameArray];
//調(diào)用指定索引的值
    NSString * nameString = [self objectInNameArrayAtIndex:0];
//    返回一個(gè)數(shù)組,數(shù)組值為指定多個(gè)多個(gè)索引值的對(duì)象
  NSArray * tempNameArray =  [self nameArrayAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 2)]];

//    這里對(duì)指針的修飾符進(jìn)行了更改,這是不安全的不增加引用計(jì)數(shù)的
    __unsafe_unretained NSArray * tempArray = [NSArray array];
//    獲取指定數(shù)組中的索引的對(duì)象添加到指定的數(shù)組中
    [self getNameArray:&tempArray range:NSMakeRange(0, 1)];

//    進(jìn)行插入操作
    [self insertNameArray:@[@"1234"] atIndexes:[NSIndexSet indexSetWithIndex:0]];
    [self insertObject:@[@"567",@"789"] inNameArrayAtIndex:0];


//    進(jìn)行刪除操作
    [self removeNameArrayObject:@"1234"];
    [self removeObjectFromNameArrayAtIndex:0];
    [self removeNameArrayAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 2)]];


//    替換操作
    [self replaceNameArrayAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 2)] withNameArray:@[@"1234",@"5678"]];
    [self replaceObjectInNameArrayAtIndex:3 withObject:@"0233"];


//獲取數(shù)組的個(gè)數(shù) countOf<Key>
-(NSUInteger)countOfNameArray{
    return self.nameArray.count;
}
//獲取指定索引的值  objectIn<Key>AtIndex:
-(id)objectInNameArrayAtIndex:(NSUInteger)index{
    
    return  [self.nameArray objectAtIndex:index];
}
//獲取指定的多個(gè)索引的值,返回一個(gè)數(shù)組對(duì)象   <key>AtIndexes:
-(NSArray *)nameArrayAtIndexes:(NSIndexSet *)indexes{
    return [self.nameArray objectsAtIndexes:indexes];
}
//獲取指定數(shù)組中索引值的對(duì)象,放到指定的數(shù)組中 get<Key>:range:
-(void)getNameArray:(NSArray *__unsafe_unretained *)buffer range:(NSRange)inRange{
    [self.nameArray getObjects:buffer range:inRange];
}
//進(jìn)行插入操作 insert<Key>:atIndexes:
-(void)insertNameArray:(NSArray *)array atIndexes:(NSIndexSet *)indexes{
    [self.nameArray insertObjects:array atIndexes:indexes];
}
//插入操作 insertObject:in<Key>AtIndex:
-(void)insertObject:(NSArray *)object inNameArrayAtIndex:(NSUInteger)index{
    [self.nameArray insertObject:object atIndex:index];
}
/刪除指定的對(duì)象
-(void)removeNameArrayObject:(NSString *)object{
    [self.nameArray removeObject:object];
}
//刪除指定的索引的對(duì)象
-(void)removeObjectFromNameArrayAtIndex:(NSUInteger)index{
    [self.nameArray removeObjectAtIndex:index];
}
//刪除指定的索引的集合對(duì)象
-(void)removeNameArrayAtIndexes:(NSIndexSet *)indexes{
    [self.nameArray removeObjectsAtIndexes:indexes];
}
//替換多個(gè)對(duì)象 replace<Key>AtIndexes:with<Key>:
-(void)replaceNameArrayAtIndexes:(NSIndexSet *)indexes withNameArray:(NSArray *)array{
    [self.nameArray replaceObjectsAtIndexes:indexes withObjects:array];
}
//替換一個(gè)對(duì)象 replaceObjectIn<Key>AtIndex:withObject:
-(void)replaceObjectInNameArrayAtIndex:(NSUInteger)index withObject:(id)object{
    [self.nameArray replaceObjectAtIndex:index withObject:object];
}

KVC底層原理分析

setValue:forKey:賦值原理如下:
1.去模型中查找有沒(méi)有對(duì)應(yīng)的setter方法:例如:setIcon方法,有就直接調(diào)用這個(gè)setter方法給模型這個(gè)屬性賦值[self setIcon:dic[@"icon"]];
2.如果找不到setter方法,接著就會(huì)去尋找有沒(méi)有icon屬性,如果有,就直接訪問(wèn)模型中的icon屬性,進(jìn)行賦值,icon=dict[@"icon"];
3.如果找不到icon屬性,接著又會(huì)去尋找_icon屬性,如果有,直接進(jìn)行賦值_icon=dict[@"icon"];
4.如果都找不到就會(huì)報(bào)錯(cuò):[<Flag 0X7fb74bc7a2c0> setValue:forUndefinedKey:]
如果對(duì)某個(gè)類,不允許使用KVC,可以通過(guò)設(shè)置 accessInstanceVariablesDirectly 控制。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 開始 關(guān)于鍵值編碼 鍵值編碼是一種機(jī)制,通過(guò)NSKeyValueCoding非正式協(xié)議,對(duì)象采用這種機(jī)制提供對(duì)其屬...
    影痕殘碎閱讀 1,319評(píng)論 0 2
  • 什么是鍵值編碼 什么是鍵值編碼 訪問(wèn)實(shí)例變量可以通過(guò)訪問(wèn)器訪問(wèn),也可以將屬性設(shè)置為@public。 與此相對(duì),鍵值...
    陳_振閱讀 567評(píng)論 0 1
  • 關(guān)于鍵值編碼 鍵值編碼(KVC)是一種由NSKeyValueCoding非正式協(xié)議提供的機(jī)制,對(duì)象采用該機(jī)制來(lái)提供...
    漸z閱讀 1,181評(píng)論 0 0
  • 1、介紹: KVC鍵值編碼在iOS中允許開發(fā)者通過(guò) Key 直接訪問(wèn)對(duì)象的屬性,或者給對(duì)象的屬性或者成員變量賦值,...
    尋形覓影閱讀 776評(píng)論 0 5
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒(méi)有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,665評(píng)論 1 32

友情鏈接更多精彩內(nèi)容