7

在通过 Monotouch 切换到 iOS 开发之前,我使用了 ObjectiveC。自从我想到一件事“键值编码”(KVC)。我一直不明白它有什么用,它背后的魔力是什么。

据我了解,它只是名称和值的集合,例如 .NET 的NameValueCollection: 而不是设置anObject.Address = "An address Value"你会写anObject.Properties["Address"] = "An address value". 伟大的。所以呢?因为这对我来说似乎太容易了,所以我确信这不可能。

还是因为 .NET 有反射,因此不需要键值编码之类的东西?我可以获取“ anObject”的类型并使用反射循环其所有属性并查找名为“地址”的属性,然后使用反射设置值。这可能是KVC的类比吗?

我希望有人是 ObjC 和 C#/.NET 方面的专家,他可以向我解释好处是什么,以及它将如何转化为 .NET。请不要只将我指向 Apple 的文档。我知道这一切。我试图通过不了解 KVC 来了解我的编码生活中是否缺少某些东西?还是我可能在 .NET 中使用了类似的东西,但不知道如果我使用的是 ObjC,它会转化为 KVC?

4

3 回答 3

11

来自每天使用这两种方法可能已经 3 年的人:

正如您所知道的,在 KVC 中没有什么是不能用 C# 中的字典和 NameValueCollections 来完成的。

最大的不同是 KVC 是用该语言构建的。Obj-C 中的一个对象一个 NameValueCollection。您无需更改开发方式(从类和属性到字典)即可使用它。您可以使用所需的属性创建对象,然后调用 valueForKey:@"name",一切仍然有效。

现在你可以说:“是的,很酷,但我可以通过反射来做到这一点!”。当然可以,但就像以前一样,你必须再次改变你的开发方式,这还不包括反射通常要慢得多的事实。

KVC 的另一个很酷的特性是它允许您使用 KVO,它基本上允许您注册以接收有关任何对象更改的通知,而无需在这些对象中编写一行代码。因此,在应用程序中的任何对象中,您都可以调用“addObserver:forKeyPath:”,并在应用程序中的其他任何人更改该属性时接收回调。这对于实时应用程序非常有用,例如 iOS 应用程序。

同样,您可以在 C# 中实现 KVO(例如 MVVM 框架一直这样做),但您必须为此编写额外的代码。在 Obj-C 中,它是用该语言构建的。

于 2012-02-25T23:18:52.623 回答
7

我在 MonoMac(MonoTouch 的对等项目,但用于构建 Mac 应用程序)的上下文中对此进行了博文:

http://tirania.org/monomac/archive/2010/Dec-07.html

键值编码是一组允许应用程序使用字符串访问对象属性的实践。这类似于 Silverlight 中的绑定表达式。在这两种情况下,目的都是允许不直接访问您的本机代码的工具从您的程序中访问属性。

特别是,这很有用,因为某些 API 可以利用这一点。例如,CoreAnimation 可以在给定对象的“路径”的情况下为属性设置动画。例如,您可以这样做:

var animateX = CAKeyFrameAnimation.FromKeyPath ("position.x");
pos.Values = new NSNumber [] { 0, 10, 60 };
layer.AddAnimation (animateX, "move");

在这种情况下,“position.x”引用了图层的位置,并且在该位置内它是 X 组件。

上面的博客文章详细介绍了如何实际公开自己的对象以参与此协议(注册自己的属性以使它们对键值编码系统可见)。

另一位 MonoMac 开发人员 Kenneth 在这里广泛地发表了关于此的博文:

http://cocoa-mono.org/archives/153/kvc-kvo-and-cocoa-bindings-oh-my-part-1/

特别是他处理了与反射的相似之处,并向您展示了如何使用 [Export] 将您的 C# 代码也转换为 KVC 兼容代码。

于 2012-02-26T17:47:21.520 回答
4

如果您访问这样的属性

anObject.Address = "An address Value"

代码将非常“静态”。它将始终访问Address

您可以像这样创建更动态的代码

void SetProperty (string propertyName, string value)
{
    anObject.Properties[propertyName] = value;
}

如果您在编译时不知道要访问哪个属性,您可以这样做。

在 c# 中,您通常会使用 aDictionary<TKey,TValue>来存储键/值对。c# 不支持像在 Objective-C 中那样通过 KVC 自动访问属性。您可以将该属性声明为

public Dictionary<string,string> Properties { get; private set; }

并在类构造函数中实例化它

Properties = new Dictionary<string,string>();

那么你可以像这样访问它

anObject.Properties[propertyName] = value;

或者您将不得不使用Reflection来访问该属性

Type type = anObject.GetType();
// Or   Type type = typeof(TypeOfAnObject);
PropertyInfo prop = type.GetProperty(propertyName);
prop.SetValue(anObject, propertyValue, null);

但是,这不是很有效。

于 2012-02-25T21:29:39.863 回答