3
votes

Under ARC, I create a NSDictionary which I assign to a property. Then I set it as the void* context parameter of KVO:

[obj addObserver:self 
      forKeyPath:kp 
         options:NSKeyValueObservingOptionNew 
         context:(void*)dict];

The KVO programming guide states that:

Note: The key-value observing addObserver:forKeyPath:options:context: method does not maintain strong references to the observing object, the observed objects, or the context. You should ensure that you maintain strong references to the observing, and observed, objects, and the context as necessary.

So it does not hold a strong reference to dict. I think ARC has no problem with this because it is just an argument.

When I get the callback I extract the dictionary like this:

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

    NSDictionary *dict = (__bridge NSDictionary*)context;
    //...

}

So I remember there were catches with ARC and void* and I think it was to use __bridge when you cast a void* to an Objective-C object pointer type when you wouldn't have to call -release in manual retain counting code. Because I didn't create ownership here I just do __bridge so ARC won't overrelease it.

But do I have to do something special for ARC to SET the dictionary as argument? Xcode doesn't complain but I have a feeling something is wrong.

2

2 Answers

0
votes

Basically context is not for passing an object, just to pass an identifier (such as an address) so that the specific item can be identified.

This is different from NSNotification that can pass an object declared as: object:(id)anObject, not context:(void *)context.

From SO answer by @nall:

When you register for the notification you can also specify a context value. The last value is simply this value returned to you. If you don't have any context-specific information, passing nil to addObserver: is appropriate.

See: Mike Ash on "context"

0
votes

I feel like your basic assumption is wrong, in that arc doesn't care about void * at all and you also aren't passing a reference to an object(in this context it is just a pointer)... ARC has no work to do there.