方法:
- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;
- (void)setValue:(id)value forKey:(NSString *)key;
- (id)valueForKeyPath:(NSString *)keyPath;
- (id)valueForKey:(NSString *)key;
key和keyPath的区别:
-key
只能放当前对象的属性,如:“age”
;
-keyPath
可以路径,如:“student.age”
;
setValue:forKey: 赋值的原理
- 第一步,按顺序查找
setKey:
、_setKey:
方法; - 都没找到,查看
accessInstanceVariablesDirectly
方法返回值是否为YES
; - 如果是,则继续按顺序查找:
_key
、_isKey
、key
、isKey
; - 如果布尔值为
NO
,或者最后还是没查找到对应的方法,则抛出异常:setValue:forUndefinedKey:
。
value:forKey: 获取值的原理
- 第一步,按顺序查找
getKey:
、key:
、isKey:
、_key:
方法; - 都没找到,查看
accessInstanceVariablesDirectly
方法返回值是否为YES
; - 如果是,则继续按顺序查找:
_key
、_isKey
、key
、isKey
; - 如果布尔值为
NO
,或者最后还是没查找到对应的方法,则抛出异常:valueForUndefinedKey:
。
扩展
1、通过KVC修改属性,会触发KVO吗?
- 会。
原理:
[person setValue:@10 forKey:@"age"]
的底层实现:
[person willChangeValueForKey:@"age"];
person->_age = 10;
[person didChangeValueForKey:@"age"];
而didChangeValueForKey:
内部会调用observer的observeValueForKeyPath:ofObject:change:context:
方法,即:KVO。