(KVO) Is it possible to remove all observers of an object without knowing who is observing?
Here's my current scenario: Have an object and I am making a copy of it so that I can change properties without touching the original. When I'm done with the copy, it gets dealloc'd, but I get the following warnings:
An instance 0x6080001250a0 of class LineGraphic was deallocated while key value observers were still registered with it. Current observation info: <NSKeyValueObservationInfo 0x618000043ea0> (
<NSKeyValueObservance 0x6180000c1ce0: Observer: 0x6000001834d0, Key path: points, Options: <New: NO, Old: YES, Prior: YES> Context: 0x0, Property: 0x600000056fe0>
<NSKeyValueObservance 0x6180000c1e30: Observer: 0x6000001834d0, Key path: shadow, Options: <New: NO, Old: YES, Prior: YES> Context: 0x0, Property: 0x600000057460>
<NSKeyValueObservance 0x6180000c9bc0: Observer: 0x6000001834d0, Key path: secondHeadStyle, Options: <New: NO, Old: YES, Prior: YES> Context: 0x0, Property: 0x60000005d7c0>
<NSKeyValueObservance 0x6180000c1ff0: Observer: 0x6000001834d0, Key path: lineStyle, Options: <New: NO, Old: YES, Prior: YES> Context: 0x0, Property: 0x600000051640>
<NSKeyValueObservance 0x6180000c1f10: Observer: 0x6000001834d0, Key path: fillColor, Options: <New: NO, Old: YES, Prior: YES> Context: 0x0, Property: 0x600000054f70>
<NSKeyValueObservance 0x6180000c1b20: Observer: 0x6000001834d0, Key path: strokeWidth, Options: <New: NO, Old: YES, Prior: YES> Context: 0x0, Property: 0x600000054d30>
<NSKeyValueObservance 0x6180000c2140: Observer: 0x6000001834d0, Key path: strokeColor, Options: <New: NO, Old: YES, Prior: YES> Context: 0x0, Property: 0x6000000548b0>
<NSKeyValueObservance 0x6180000c1d50: Observer: 0x6000001834d0, Key path: firstHeadStyle, Options: <New: NO, Old: YES, Prior: YES> Context: 0x0, Property: 0x600000055060>
<NSKeyValueObservance 0x6180000c1ea0: Observer: 0x6000001834d0, Key path: opacity, Options: <New: NO, Old: YES, Prior: YES> Context: 0x0, Property: 0x6080002421f0>
<NSKeyValueObservance 0x6180000c1f80: Observer: 0x6000001834d0, Key path: visibleOpacity, Options: <New: NO, Old: YES, Prior: YES> Context: 0x0, Property: 0x608000247560>
<NSKeyValueObservance 0x6180000ca090: Observer: 0x6000001834d0, Key path: rotation, Options: <New: NO, Old: YES, Prior: YES> Context: 0x0, Property: 0x60800024a590>
)
This is how I copied my object:
ImageDocument *selfCopy = [self copy];
I believe that when I do this, all property watchers LineGraphic
are also observing copy LineGraphic
in copy self
. Then, when selfCopy
dealloc'd is received, these warnings appear.
I figured that the best solution would be to simply remove the observers - because in the case of the copy, they don't have to be there.
From searching the web, I could only find ways to delete all observations that the object creates. But I need it in a different way to remove all observers from the object. Also many resources always refer to removing observers for NSNotifications
, whereas I need to remove observers for key paths (KVO)
I thought that if all else fails, I could iterate over all observers of the observable ( LineGraphic
), but the problem is that one: there are many observers, and two: if there are more observers added later, they would have to add removing them here in this code. So this solution really won't work well
source to share
Is it possible to remove all observers of an object without knowing who is observing?
Yes, BUT ...
Your problem is that the KVO model is designed around the idea that an observer is responsible for registering and de-indicating as an observer; the observed objects are responsible; and you are trying to usurp this model.
Methods removeObserver
throw an exception if the object being deleted is not an observer; if you delete the observer yourself, then the observer will not know, at some point will try to unregister, and you will get an exception, not a good one.
So think very carefully about what you really want to do.
Still want to do this?
I believe that when I do this, all property watchers
LineGraphic
are also observing copyLineGraphic
in copyself
.
This is not the expected normal behavior, KVO is used to look at a specific instance and copy that instance creates a new separate object. It is possible to do a copy so that the observers are copied, but this would be confusing at all and not recommended - the observers will not know that they are currently observing another object, and therefore cannot deregister later ...
Still want to do this?
Well, you were warned ... consider revisiting, the details are left to you.
Alternative suggestion:
Don't usurp KVO, work with it.
Add a method to your class that updates an instance (your original object) from another instance (the replacement object). This method can directly update base variables for properties without calling setters and calling methods from KVO willChange
and groups didChange
, so no notification is made until the entire object has been updated.
You can now create your "replacement" and then update the original. Your observers will continue to observe the same object when it is time to de-register.
NTN
source to share