Key-Value Observing an NSMutableSet
Asked Answered
C

3

7

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?

Cobbett answered 19/6, 2011 at 16:16 Comment(1)
There is some related discussion can be found in the following link https://mcmap.net/q/1623468/-kvo-on-an-nscountedsetBloodhound
S
6

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.

Substation answered 19/6, 2011 at 18:18 Comment(1)
Great, that I finally understand :) I've gone and written my own accessors to the list, as suggested, and know yet a bit more about KVO. Thanks Josh & Girish!Cobbett
W
1

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.

Winchester answered 15/3, 2016 at 2:22 Comment(0)
L
0

It's actually pretty clear when you relate it to an example:

If you have a class Bank that has a NSSet of Accounts, don't add the observer on Bank.accounts, add the observer on Account.bank

Lollipop answered 24/1, 2018 at 12:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.