setValue:forKey: 的调用流程

graph LR
A[setValue:forKey:] --> B[setKey:] 
subgraph set
B --> B1[setIsKey:]
end
B1 --> C{+accessInstanceVariablesDirectly}
C --> D[_key]
subgraph instance
D[_key] --> _isKey --> key --> E[isKey]
end
E --> F[setValue:forUndefinedKey:]

valueForKey: 的调用流程

graph LR
subgraph get
A[getKey] --> Ag[key] --> A1[isKey]
end
subgraph count
A1 --> countOfKey --> A2[objectInKeyAtIndex]
end
A2 --> A3{accessInstanceVariablesDirectly}
A3 --> A4[_isKey]
subgraph instance
A4 --> key --> A5[isKey]
end
A5 --> valueForUndefinedKey:

其它

  1. kvc 官方文档现已说的很理解,上述为首要流程,文档中还有其他小细节。

小细节

  1. setValue:forUndefinedKey: 被调用后会产生什么?

答:产生 NSUndefinedKeyException 崩溃,但是咱们能够重写它。

  1. setNilForKey: 直接调用会产生什么?

Given that an invocation of -setValue:forKey: would be unable to set the keyed value because the type of the parameter of the corresponding accessor method is an NSNumber scalar type or NSValue structure type but the value is nil, set the keyed value using some other mechanism. The default implementation of this method raises an NSInvalidArgumentException. You can override it to map nil values to something meaningful in the context of your application.

  1. 哪些三方库中有运用到?

MJExtension 最终给特点赋值的时分运用到了,由于他运用的是 kvc,而 YYModel 运用的是对象的 setter 办法,所以他在最终的赋值阶段要比 YYModel 慢很多。

测试

KVC kvc = [[KVC alloc] init];
CFTimeInterval begin = CACurrentMediaTime();
for (int i = 0; i < 1000000; i ++) {
    [kvc setValue:@"123" forKey:@"abc"];
}
CFTimeInterval end = CACurrentMediaTime();
NSLog(@"---%f", end - begin); // 0.03
for (int i = 0; i < 1000000; i ++) {
    [kvc setAbc:@"123"];
}
CFTimeInterval end1 = CACurrentMediaTime();
NSLog(@"===%f", end1 - end); // 0.009

能够看出 kvc 的功能仅为直接调用 setter 办法功率的 1 / 3