常用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);
}