Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apple's Key Value Coding - can somebody explain to a C# developer why I would need this and what it does?

Before I switched to iOS development via Monotouch I played around a bit with ObjectiveC. Ever since one thing has been on my mind "Key Value Coding" (KVC). I have never understood what it is good for and what the magic behind it is.

For my understanding it is just a collections of names and values, like .NET's NameValueCollection: Instead of setting anObject.Address = "An address Value" you would write anObject.Properties["Address"] = "An address value". Great. So what? Because this appears to be too easy to me I'm sure that can't be it.

Or is it because .NET has reflection and therefore has no need for something like Key-Value-Coding? I can grab the type of "anObject" and use reflection to loop all of its properties and look for the one called "Address" and then use reflection to set the value. Is that maybe the analogy of KVC?

I'm hoping there is somebody out there who's a pro in ObjC and C#/.NET who can explain to me what the benefits are and how it would translate into .NET. Please don't just point me to Apple's documentation. I know all that. I'm trying to find out if something has been missing in my coding-life so far by not knowing KVC? Or have I maybe been using something similar in .NET not being aware that it would translate into KVC if I was using ObjC?

like image 220
Krumelur Avatar asked Feb 25 '12 21:02

Krumelur


3 Answers

From somebody who uses both every day for probably 3 years now:

As you figured out, there's nothing amazingly complex in KVC that can't be done with dictionaries and NameValueCollections in C#.

The big difference is that KVC is built in the language. An object in Obj-C IS a NameValueCollection. You don't have to change the way you develop (from classes and properties to dictionaries) to use it. You can create your object with the properties you want, and then later on call a valueForKey:@"name", and everything still works.

Now you can say: "yeah cool, but I can do that with reflection!". Sure you can, but just as before, you'll have to change the way you develop again, not counting the fact that reflection is a lot slower in general.

Another cool feature of KVC it it allows you to use KVO, which basically allows you to register to receive notifications about changes in any object without having to write a single line of code in those objects. So, in any object in your application, you can call "addObserver:forKeyPath:", and receive a callback if anybody else in your application changes that property. This is really useful for live apps, like iOS apps.

Again, you can implement KVO in C# (MVVM frameworks for example do this all the time), but you have to write extra code for that. In Obj-C, it's built in the language.

like image 129
Eduardo Scoz Avatar answered Nov 15 '22 21:11

Eduardo Scoz


I blogged about this in the context of MonoMac, the peer project to MonoTouch but used for building Mac applications:

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

Key-Value Coding is a set of practices that allow applications to access object properties using strings. This is similar to Binding Expressions in Silverlight. In both cases the purpose is to allow tooling that does not directly have access to your native code to access properties from your program.

In particular, this is useful because some APIs can take advantage of this. For example CoreAnimation can animate properties given their "path" to the object. For example, you can do:

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

The "position.x" in this case references the layer's position, and within that position it's X component.

The blog post above goes into more detail about how you can actually expose your own objects to participate in this protocol (registering your own properties to make them visible to the Key-Value-Coding system).

Kenneth, another one of the MonoMac developers blogged about this extensively here:

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

In particular he deals with the similarities with Reflection and he shows you how to use [Export] to turn your C# code into KVC compliant code as well.

like image 41
miguel.de.icaza Avatar answered Nov 15 '22 21:11

miguel.de.icaza


If you access a property like this

anObject.Address = "An address Value"

The code will be very "static". It will always access Address

You can create a more dynamic code like this

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

You would do this if you do not know at compile time which property will be accessed.

In c# you would typically use a Dictionary<TKey,TValue> for storing key/value pairs. Automatically accessing properties via KVC as in Objective-C is not supported in c#. You would either declare the property as

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

and instantiate it in the class constructor with

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

then you could access it like this

anObject.Properties[propertyName] = value;

Or you would have to use Reflection to access the property

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

However, this is not very efficient.

like image 41
Olivier Jacot-Descombes Avatar answered Nov 15 '22 21:11

Olivier Jacot-Descombes