OC原理-KVC

278 阅读1分钟

常用API

//设值
-(void)setValue:(id)value forKeyPath:(NSString *)keyPath;
-(void)setValue:(id)value forKey:(NSString *)key;
//取值
-(id)valueForKeyPath:(NSString *)keyPath;
-(id)valueForKey:(NSString *)key;

keyPath功能比key强大,不光可以设置和读取调用对象的属性值,还可以操作属性的属性

@interface Cat : NSObject
@property(nonatomic,assign)int age;
@end
@interface Person : NSObject
@property(nonatomic,assign)int age;
@property(nonatomic,strong)Cat *cat;
@end

[self.person setValue:@6 forKeyPath:@"cat.age"];//这里就必须用keyPath

setVlue:forKey:执行过程 & valueForKey:执行过程

证明代码如下

@interface Person : NSObject{
    @private
    int _age;
    int _isAge;
    int age;
    int isAge;

}
//@property(nonatomic,assign)int age; //注释掉看是否调用调用setAge:方法
@end
@implementation Person
#pragma mark - 测试setKey
//- (void)setAge:(int)age{
//    NSLog(@"%s",__func__);
//}
//- (void)_setAge:(int)age{
//    NSLog(@"%s",__func__);
//}

#pragma mark - 测试getKey
-(int)getAge{
      return 11;
}
-(int)age{
      return 12;
}
-(int)isAge{
      return 13;
}
-(int)_age{
      return 14;
}

//是否可以访问成员变量  默认可以
+(BOOL)accessInstanceVariablesDirectly{
    return YES;
}

//测试setkey
[self.person setValue:@30 forKey:@"age"];
//测试getKey
self.person->_age = 11;
self.person->_isAge = 12;
self.person->age = 13;
self.person->isKey = 14;
[self.person valueForKey@"age"];

通过KVC修改属性值可以出发KVO

奔溃解决

取值或者复制都有可能引发奔溃,创建一个分类 复写系统方法

- (void)setValue:(id)value forUndefinedKey:(NSString *)key{
    NSLog(@"kvc赋值报错:%@类中没有key:%@",[self class],key);
}
- (id)valueForUndefinedKey:(NSString *)key{
    NSLog(@"kvc取值报错:%@类中没有key:%@",[self class],key);
    return @"";
}

有时候赋值nil报错,创建一个分类 复写系统方法

[self.person setValue:nil forKey:@"age"]; 这行代码报错
- (void)setNilValueForKey:(NSString *)key{
    NSLog(@"kvc赋值报错:%@类中Key:%@呗赋值了nil",[self class],key);
}