键值编码的重点是什么? [英] What is the point of key-value coding?

查看:71
本文介绍了键值编码的重点是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从Objective-C 2.0开始,我们有了@properties和自动生成的访问器方法.那么,今天,键值编码有什么意义呢?在什么情况下最好写

[myObject setValue:foo forKey:@"bar"];

代替写作

[myObject setBar:foo];

甚至

myObject.bar = foo;

我一直看到使用KVC的文章和文档,但是总是以一种似乎仅使用属性会更好的方式出现.那么,为什么我会使用KVC?感谢您提供的所有见解.

解决方案

用文字@"bar"手写出[myObject setValue:foo forKey:@"bar"]几乎是不可取的.当我们直到运行时才知道要访问哪个属性时,通常使用KVC访问属性.

一个示例是xib中的插座.当您将文本字段的代理出口连接到xib中的文件所有者时,xib将连接记录为具有三个字段的对象:

  • 对文本字段(具有出口的对象)的引用
  • 对文件所有者占位符(连接目标)的引用
  • 插座名称,以字符串形式,@"delegate"

在运行时,xib加载器(UIKit框架的一部分)反序列化文本字段.然后,它反序列化连接对象,并使用它来建立您在xib中连接的连接. xib加载器必须设置文本字段的属性(delegate属性),但是直到您的应用程序和UIKit框架都编译很久之后,它才能在运行时加载xib之前不知道哪个属性.

另一个示例,直到运行时才知道要访问哪个属性,这是Core Animation动画化CALayer子类的自定义属性的能力(鲜为人知).假设您创建一个名为PolygonLayerCALayer子类,并具有一个名为sides的属性.您可以使用标准的CABasicAnimation设置sides属性的动画:

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"sides"];
animation.fromValue = @3;
animation.toValue = @9;
animation.autoreverses = YES;
animation.duration = 1;
[myPolygonLayer addAnimation:animation forKey:@"sides"];

Presto,Core Animation将使图层的sides属性从3到9进行动画处理,然后返回.但是,Core Animation的源代码对您的sides属性一无所知. (有关更多详细信息,请查看此问题.)

有时候,即使我们在编译时就知道该属性,我们还是使用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(核心数据的一部分)根据NSManagedObject实例表示的任何实体动态地为其提供属性.您可以使用KVC访问这些属性,尽管通常我们更喜欢

instead of writing

[myObject setBar:foo];

or even

myObject.bar = foo;

I keep seeing articles and documentation making use of KVC, but always in a way where it seems like simply using properties would be better. So why would I ever use KVC? Thanks for any and all insight.

It's almost never preferable to write out [myObject setValue:foo forKey:@"bar"] by hand, with a literal @"bar". We usually use KVC to access a property when we don't know which property we want to access until runtime.

One example is an outlet in a xib. When you connect a text field's delegate outlet to the File's Owner in the xib, the xib records the connection as an object with three fields:

  • a reference to the text field (the object that has the outlet)
  • a reference to the file's owner placeholder (the destination of the connection)
  • the name of the outlet as a string, @"delegate"

At runtime, the xib loader (part of the UIKit framework) deserializes the text field. Then it deserializes the connection object and uses it to establish the connection that you wired up in the xib. The xib loader has to set a property of the text field (the delegate property), but it doesn't know which property until it loads the xib at runtime, long after both your app and the UIKit framework were compiled.

Another example of not knowing which property to access until runtime is the (little-known) ability of Core Animation to animate a custom property of your CALayer subclass. Say you create a subclass of CALayer called PolygonLayer, with a property named sides. You can animate the sides property using a standard CABasicAnimation:

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"sides"];
animation.fromValue = @3;
animation.toValue = @9;
animation.autoreverses = YES;
animation.duration = 1;
[myPolygonLayer addAnimation:animation forKey:@"sides"];

Presto, Core Animation will animate your layer's sides property from 3 to 9 and back. Yet the source code of Core Animation doesn't know anything about your sides property. (Check out this question for more details.)

There are times we use KVC even though we know the property at compile-time. One example is when we want to take advantage of extra work KVC will do for us. For example, if you have an NSArray full of Person objects, and you want to get an array of every person's first name, you could write this:

NSMutableArray *firstNames = [NSMutableArray array];
for (Person *person in people) {
    [firstNames addObject:person.firstName];
}

But this is a case where KVC has a feature that makes it simpler. If you access a property of an array using KVC, KVC will actually access that property of every element in the array for you:

NSArray *firstNames = [people valueForKey:@"firstName"];

Another example where we might use KVC even though we know the property at compile-time is when the property is not statically declared as part of the class. For example, each NSManagedObject (part of Core Data) dynamically gives itself properties based on whatever entity that instance of NSManagedObject is representing. You can access those properties using KVC, although generally we prefer to declare them in a subclass of NSManagedObject or in a category of NSManagedObject.

这篇关于键值编码的重点是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆