limboy
limboy

Reputation: 4089

when to use KVO?

I have read many docs on KVO, but I'm still confused as to when to use it.

In case objA wants to monitor a certain property of objB, like so:

self.objB = [[ObjB alloc] init];
[self.objB addObserver:self
            forKeyPath:@"address"
               options:0
               context:nil];

so if objB's property changes, and it can only be changed by self, why not just do this:

self.objB.property = @"newValue";
[self doSomethingBasedOnNewValueOfObjBnewProperty];

instead of

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

{
    if(keyPath == @"address") {
        [self doSomethingBasedOnNewValueOfObjBnewProperty];
    }
}

It may be useful when used with a singleton, like self.objB = [ObjB sharedInstance], where properties may be changed by other objects. Is this the only use case?

Upvotes: 15

Views: 3188

Answers (2)

Mohannad A. Hassan
Mohannad A. Hassan

Reputation: 1648

Wain's answer is perfect. I'd like to contribute by stating some examples of the possible uses of KVO.

KVO can be useful in a case where some objects "say one or more view controllers" need to monitor changes in many objects.

For example, an FPS game has some views, one that shows the players interaction with each other, a view on a corner that shows the current player score and health; and a menu that shows the players' scores when a button is tapped or the game is paused. If the current player hits or gets hit by another player, you need to update the main view, by showing a successful hit or showing some sign that the player got injured, the score and health view needs to update its data and the player's scores view needs to be updated. Now suppose that you need to add a new controller objet that monitors the player's achievements by monitoring his score and his number of kills. This object also needs to get notified of any event that happens to the player.

In that case, many objects need to monitor changes of many other objects "the current player and the other players". KVO gives you a simple tool to achieve this without having to write code to handle notification registration and the actual notifications. Think how would it take you to implement it from scratch to notice the difference.


In another example, I usually tend to make a singelton loader for some data retrieved by a web service. In such case, some data is needed by many parts of the application.

For example, you want to develop an app made by a store that shows the user the available items. This app needs to show the user a table view that shows all items, a view to show items of a specific category, another view to show items on sale, another view to show the details and available quantity of a certain item. Now suppose that the app is required to refresh the data every several hours or when a user requests a refresh. That loader class can handle the refresh action by itself and the view controllers can register to the related keys. This way, the refresh is handled in one object and the other objects can just focus on their view handling logic.

Upvotes: 11

Wain
Wain

Reputation: 119041

Not all instances of all classes are created and edited only by the same instance (which is effectively what your example indicates).

KVO is a generic method by which one instance can observe changes on another and receive notifications of what has happened. Those changes could be triggered from anywhere.

Say you added a 3rd party library to your project. You don't know how it's implemented. Calling one method could change multiple different properties in the library class instance. KVO provides an easy way for you to monitor and react to those changes.

KVO also supplies 'Dependent Keys' which allows you to configure relationships between keys so you can say "the value of this property depends on that of one or more other attributes in another object" and KVO will tell you when it happens. This could be particularly useful in a managed object subclass say, if you have a transient key that holds a cached value for some persistent key and the cache needs to be updated whenever the persistent value changes...

Upvotes: 18

Related Questions