Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Key-Value Observing an NSMutableSet

In a plain class I have a NSMutableSet property. Whenever objects are added to or removed from the set, I want to perform some custom code. I know I could write a few addObjectToSet:-like methods to the class, but I was wondering if there's a more elegant solution with direct KVO on the set.

As it turns out, NSSet will raise an exception when you try to add an observer to it. Not surprisingly, for there's probably no named keyPath to observe. The documentation is pretty clear about the exception, but I don't understand the suggested workaround:

Instead of observing a set, observe the unordered to-many relationship for which the set is the collection of related objects.

Could someone reiterate what this means? And what a workaround would then look like?

like image 228
epologee Avatar asked Jun 19 '11 16:06

epologee


2 Answers

That's a pretty dense way of saying "don't add an observer to the set itself, add an observer to the class that contains the set":

[myObjWithASetAsIvar addObserver:self
                      forKeyPath:@"nameOfIvarHoldingTheSet"
                         options:NSKeyValueObservingOptionNew
                         context:nil];

The one tricky bit is that you need to wrap all your accesses to the set in order for the proper notifications to be sent. In the class containing the set:

[self willChangeValueForKey:@"nameOfIvarHoldingTheSet"];
// Do something with the set
[self didChangeValueForKey:@"nameOfIvarHoldingTheSet"];

There are also two notification methods specifically for sets: willChangeValueForKey:withSetMutation:usingObjects: and didChangeValueForKey:withSetMutation:usingObjects:; you may find that they work better for you than the generic "value change" methods.

All that said, I believe that the solution you mentioned in your first paragraph, and outlined by Peter Hosey in the question Girish linked to, is probably the best way to go.

like image 195
jscs Avatar answered Oct 27 '22 02:10

jscs


From Apple's documentation on NSSet (and, by inference and implication, NSMutableSet):

NSSet objects are not observable, so this method raises an exception when invoked on an NSSet object. Instead of observing a set, observe the unordered to-many relationship for which the set is the collection of related objects.

I'm glad you seem to have found an answer, but the fact that your initial approach was flawed (in that you assumed you could use addObserver on an NSSet), this needed to be mentioned, regardless.

like image 24
James Bush Avatar answered Oct 27 '22 01:10

James Bush