Monday, December 5, 2011

What is Key-Value Coding (KVC) and Why We Need It?

Before I discuss what is Key-Value Coding (KVC), it's very important that you understand the concept of KeyKey-Value and Key-Path.

What is Key?

Lets say we have a class named "Person" and it has 2 ivars called "name" and "age". We will call these ivars as "keys" but they will be strings => our ivar called "name" will have the key called @"name" and "age" ivar will have the key called @"age".

What is Key-Value?

Since ivar is suppose to store some value/data => our keys will have a value/data and we will call it key-value.

And What is Key-Path?

Lets say we have 2 classes as follows.

  @interface Passport {  	NSString *passportId; } @end
  @interface Person {  	NSString  *name; 	NSInteger *age;  	Passport  *passport; }  @end

Now what will be key for Passport class ivar called "passportId"? Answer is, it will depend on the perpective. If we will look it from the Person class, its key will be @"passport.passportId" and if we look it from the Passport class itself, it will be@"passportId".

So this "Path tracing" of key is called "Key-Path"

What is Key-Value Coding (KVC)?

In object oriented (OO) programming, you will also make getters and setters to set and access the values of your ivars, which is very good thing from the perspective of Encapsulation. But KVC is the concept of setting and getting the values of ivars with keys instead of getter and setters like this.

  Person *person = [[Person alloc] init];  // To set value of ivar with keys [person setValue:@"Adil" forKey:@"name"];  // To get the value of name ivar with keys [person valueForKey:@"name"];

Why We Need This?

The obvious question which arise from this, if we can do the same thing with getters and setters, why go through this hassle? The simple answer is, it reduce the amount of code we write but how? Just compare the following 2 codes for the following senario.

  /* Lets say we need the value associated with our ivars at run time but we don't know in advance  which ivar need to be returned. */  // Code 1 - without KVC  - (id*) returnIvarValueFor:(NSString*) key {  	if ([key isEqualToString:@"name"]) { 		return [self name]; 	} else if ([key isEqualToString:@"age"]) { 		return [self age]; 	} }  // code 2 - with KVC  - (id*) returnIvarValueFor:(NSString*) key {  	return [self valueForKey:key]; }

Code 2 is obviously simpler and easy to understand.