Wednesday, February 4, 2009

KVO and the iPhone SDK

One of the common misconceptions about the iPhone SDK is that it doesn't support Key-Value Observation, or KVO. I suspect that the reason for this misconception is that the most conspicuous uses of KVO in Cocoa—Core Data and Bindings—has not been brought to the iPhone.

Now, KVO is not used much in the iPhone SDK. I don't think we ever mentioned it in the book. But it is available. The NSKeyValueObservation informal protocol is part of the iPhone SDK. It's completely opt-in on the iPhone, however. When you create an application project in Xcode, none of your objects are observing any other. Well, there might be some KVO being used behind the scenes (in fact, I suspect there is), but most people won't encounter it.

But, any Objective-C object can register to receive notifications when a property of another object is changed. An object can even observe itself. Here is how you register to observe an object. In this example, theObject is being told to notify theObserver any time the property called name

[theObject addObserver:theObserver forKeyPath:@"name" options:0 context:nil];

Now, theObserver just has to implement this method to find out when theObject.name changes:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{

}

This is really quite a flexible bit of functionality. When registering as an observer, you can use the options: argument to tell the KVO system whether you want the old value, the new value, or the original value of the property being changed. You can even use keypaths, not just keys. So, if name weren't a string, but were actually another object with component string properties called firstName and lastName, we could pass in a key path of @"name.firstName" to indicate that we want to get notified when the firstName property of name changes.

This is some pretty cool stuff. I used this functionality recently in SQLitePersistentObjects to set the dirty flag on objects so that they only get saved when something has changed since it was loaded, or the last time it was saved. In the init method, I simply iterate through the properties of the object (including those declared in superclasses), and for any property that isn't read-only, I register it as an observer of itself. Then, when the object gets notified of any change, I mark the object as dirty, which lets me know to actually save the data when the save method is called.

In the future, I may implement a more sophisticated version that only updates the actual properties that are dirty rather than saving the whole object.



8 comments:

J Bondo said...

I use KVO extensively in Deep Green where various user interface elements observe states in the model layer.

The toolbar updates itself when the last move changes. So does the turn indicator. The gear/engine button starts animating when the engine is working. The drawer comes out when game mode changes to Playback or Setup etc.

Coding this way makes a really nice and clean abstraction between model and views. Without KVO, I'd be doing this manually and it would be a nightmare to maintain.

When adding to the UI, if it observes the relevant areas of the model, things just work. No need to go back and code support for the newly added UI.

Non-KVO coding could easily require the model to know about the UI which is certainly not what you want.

DavidPhillipOster said...

Hmm. I prefer non-KVO coding where the model informs its delegate of changes. Less magic. Easier to step through the code when debugging. No need for string compare in the observeObject method to discover what's really going on. Easier lifetime management. See http://www.dribin.org/dave/blog/archives/2010/01/18/refactored_mac_iphone_app_with_tests/ for an example of using a delegate and a custom protocol to inform the UI of changes.

aikhan said...

David wouldn't the delegates beat the whole purpose of MVC. Model would get too dependent on the View & maybe wont survive as standalone. Even if you make your delegates @optional but still I think KVO is better approach.....

Edwin said...

scrub m65 kamagra attorney lawyer body scrub field jacket lovegra marijuana attorney injury lawyer

JeansPilot said...

JeansPilot offers the chance to buy a large variety of men’s and women’s jeans clothing from the world famous Italian Brands.
Online jeans clothing store looks for original fashion clothing sales and clearances of worldwide known designers. We participate in fashion auctions to get the lowest possible price for Top quality Clothes, Shoes and Accessories.
Buy Jeans

Paul said...

Very helpful. I was wondering if someone could comment on the performance implications of this. I've been using notifications for some model-view connections but observing might have been better and easier to manage.

Is there a difference between notifications and kvo in terms of performance?

By the way, your book was one of the key gateways into iOS development, thanks for the good work on it.

CHEAPSOCCERUNIFORM said...

I really like this website , and hope you will write more ,thanks a lot for your information.
Now it will be very cold in winter, in order to keep warm yourself, moncler company has provide jackets for you, so it is better to own moncler jackets yourselif as soon as possible. Eeveryone love fashion clothing, polo ralph lauren is very popular all over world, that is my dream to get ralph lauren.We know Ray Ban by America soldier, all of them wear ray ban sunglasses when they walk on the road, it is fashionable for you. Most of people like to wear jeans, it is very modern when wearing true religion jeans in the street.

h4ns said...

What youre saying is completely true. I know that everybody must say the same thing, but I just think that you put it in a way that everyone can understand. I also love the images you put in here. They fit so well with what youre trying to say. Im sure youll reach so many people with what youve got to say.

Arsenal vs Huddersfield Town live streaming
Arsenal vs Huddersfield Town live streaming
Wolverhampton Wanderers vs Stoke City Live Streaming
Wolverhampton Wanderers vs Stoke City Live Streaming
Notts County vs Manchester City Live Streaming
Notts County vs Manchester City Live Streaming
Bologna vs AS Roma Live Streaming
Bologna vs AS Roma Live Streaming
Juventus vs Udinese Live Streaming
Juventus vs Udinese Live Streaming
Napoli vs Sampdoria Live Streaming
Napoli vs Sampdoria Live Streaming
Fulham vs Tottenham Hotspur Live Streaming
Fulham vs Tottenham Hotspur Live Streaming
AS Monaco vs Marseille Live Streaming
AS Monaco vs Marseille Live Streaming
Alajuelense vs Perez Zeledon Live Streaming
Alajuelense vs Perez Zeledon Live Streaming
Technology News | News Today | Live Streaming TV Channels