自 Objective-C 2.0 以来,我们已经拥有@properties
并自动生成访问器方法。那么今天,键值编码的意义何在?什么情况下最好写
[myObject setValue:foo forKey:@"bar"];
而不是写
[myObject setBar:foo];
甚至
myObject.bar = foo;
我不断看到使用 KVC 的文章和文档,但总是以某种方式似乎简单地使用属性会更好。那么我为什么要使用 KVC?感谢您的任何见解。
自 Objective-C 2.0 以来,我们已经拥有@properties
并自动生成访问器方法。那么今天,键值编码的意义何在?什么情况下最好写
[myObject setValue:foo forKey:@"bar"];
而不是写
[myObject setBar:foo];
甚至
myObject.bar = foo;
我不断看到使用 KVC 的文章和文档,但总是以某种方式似乎简单地使用属性会更好。那么我为什么要使用 KVC?感谢您的任何见解。
[myObject setValue:foo forKey:@"bar"]
用文字写出来几乎永远不会更可取@"bar"
。当我们直到运行时才知道要访问哪个属性时,我们通常使用 KVC 来访问一个属性。
一个例子是 xib 中的插座。当您将文本字段的委托出口连接到 xib 中的文件所有者时,xib 将连接记录为具有三个字段的对象:
@"delegate"
在运行时,xib 加载器(UIKit 框架的一部分)反序列化文本字段。然后它反序列化连接对象并使用它来建立您在 xib 中连接的连接。xib 加载器必须设置文本字段的属性(delegate
属性),但它不知道哪个属性,直到它在运行时加载 xib,在您的应用程序和 UIKit 框架都被编译很久之后。
另一个直到运行时才知道要访问哪个属性的例子是 Core Animation (鲜为人知)能够为CALayer
子类的自定义属性设置动画。假设您创建了一个CALayer
名为的子类PolygonLayer
,并具有一个名为 的属性sides
。sides
您可以使用标准为属性设置动画CABasicAnimation
:
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"sides"];
animation.fromValue = @3;
animation.toValue = @9;
animation.autoreverses = YES;
animation.duration = 1;
[myPolygonLayer addAnimation:animation forKey:@"sides"];
sides
Presto,Core Animation 将为您的图层属性设置动画,从 3 到 9 并返回。sides
然而,Core Animation 的源代码对您的属性一无所知。(查看这个问题了解更多详情。)
即使我们在编译时知道该属性,有时我们也会使用 KVC。一个例子是当我们想要利用 KVC 为我们做的额外工作时。例如,如果您有一个NSArray
完整的Person
对象,并且您想要获取每个人的名字的数组,您可以这样写:
NSMutableArray *firstNames = [NSMutableArray array];
for (Person *person in people) {
[firstNames addObject:person.firstName];
}
但在这种情况下,KVC 具有使其更简单的功能。如果您使用 KVC 访问数组的属性,KVC 实际上会为您访问数组中每个元素的该属性:
NSArray *firstNames = [people valueForKey:@"firstName"];
即使我们在编译时知道属性,我们也可能使用 KVC 的另一个示例是,当属性未静态声明为类的一部分时。例如,每个 NSManagedObject(Core Data 的一部分)根据该实例NSManagedObject
所代表的任何实体动态地赋予自己属性。您可以使用 KVC 访问这些属性,尽管通常我们更喜欢将它们声明NSManagedObject
在NSManagedObject
.
如果您使用 Key Value Observers 来检测对象上的值变化,KVC 会很有用。如果您想使用 KVO,并且@properties
您必须将每个 mutator 方法包装为:
[self willChangeValueForKey:@"bar"];
bar = foo;
[self didChangeValueForKey:@"bar"];
有时您直到运行时才知道要设置/获取的属性。
在这种情况下,您可以通过将属性键路径构造为字符串来使用 KVC。
例如,我有一个具有多个 NSArray 属性的对象,我想保留它们更新的最后一个 NSDate。
假设我有一个名为:comments的数组属性和一个名为likes的数组属性。
我定义了一个属性:commentsLastModified 和 likesLastModified。更新数组时(我将属性名称作为字符串),我使用:
[object setValue:[NSDate date] forKey:[NSString stringWithFormat:@"%@%@", arrayString, @"LastModified"];