0

How do I know what items my object is key-value observing?

The only way I've been able to find out if I'm already observing is to try to remove the observation. If an exception is thrown, then I wasn't observing.

for (AVPlayerItem *item in itemsToRemove) {
    @try{
        [item removeObserver:self forKeyPath:@"status" context:(__bridge void *)(foo)];
    }@catch(id anException){
        //wasn't observing
    }
}

EDIT: I'm considering using my own dictionary to track observation but that seems redundant since a KVO Dictionary does exist somewhere. Unfortunately there is no API access.

quantumpotato
  • 9,637
  • 14
  • 70
  • 146
  • Here http://stackoverflow.com/questions/27482173/how-to-check-key-value-observing-in-objectivec-for-dictionary-of-arrays/27482567#27482567 you can see an example and the two methods the observing fire. – Onik IV Dec 16 '14 at 18:14
  • 1
    @OnikIV OP wasn't asking how to observe. He was asking how to know if he was observing. – Rob Dec 16 '14 at 18:22
  • Yes @Rob, If He read all the answer posted, He well see than when you observe some property this method: "-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { // Here your actions depends on the key path... }" is called. In other words, If you don't observe any key path this method won't be called. – Onik IV Dec 16 '14 at 18:24
  • 1
    @OnikIV Again, the OP undoubtedly already knows that. He's asking a far more subtle question which your other answer does not address. He's got a design in which he somehow doesn't know if the observer has been added or not and is asking how to conditionally remove observer if and only if the observer had been previously added. (Personally, I'd maintain a state variable rather than try/catch technique.) But to refer him to an answer about how to add and use an observer (esp one that doesn't contemplate the removal of the observer) is to fundamentally misunderstand the question at hand. – Rob Dec 16 '14 at 18:33
  • Thanks for clarifying @Rob. I was considering adding my own dictionary but using the try/catch solves the crash succintly. What did you mean by state variable? if [self removeObserver].. ? – quantumpotato Dec 16 '14 at 18:57
  • Regarding state variable, was thinking of your own custom Boolean property that kept track of whether you had added the observer or not. Or, in more complicated scenarios, an array that kept track of what observers you had added. There are bunch of ways to do it. But the general idea is to just keep track of whether you added the observer or not, because the OS doesn't provide a mechanism to do this for you. – Rob Dec 16 '14 at 19:04
  • Oh, for sure. I would have to use an NSDictionary, since there are multiple items that can be observed. Good discussion thanks. – quantumpotato Dec 16 '14 at 19:06

2 Answers2

3

It seems there is no other option than catching the exception, even NSHipster recommends to do so. However, at least in my case, it was hardly ever needed to do the check. After all, you are the one who controls the observers.

You can use a wrapper (like FBKVOController) which adds more sanity to the raw KVO (and makes observing a lot easier, allowing to use blocks). Among other features, it doesn't crash when trying to remove a nonexistent observer:

 @discussion If not observing object key path, or unobserving nil, this method results in no operation.
 */
- (void)unobserve:(id)object keyPath:(NSString *)keyPath;
Michał Ciuba
  • 7,876
  • 2
  • 33
  • 59
  • I love NSHipster but I think their suggestion is misleading and out of date as of today. Exceptions are used as emergency exit in Objective-C, it wasn't like that before! So your suggestion to use KVOController is much better than try-catch. – pronebird Dec 17 '14 at 12:35
  • 1
    I think that, at the time of writing, NSHipster was aware that exceptions should be generally avoided. But in this case catching an exception is a workaround for a poorly designed KVO API. – Michał Ciuba Dec 17 '14 at 13:01
0

There is no way to know that until you add some boolean flag to your controller and use it to mark and check if your registered for KVO. Normally you should balance out registration and unregistration from KVO observation.

Using exception under ARC is bad and may lead to memory leaks until you use -fobjc-arc-exceptions.

Long story short: Exceptions are expensive, that's why ARC does not properly handle them until you explicitly ask. There is an explanation to that: https://stackoverflow.com/a/4649234/351305

Community
  • 1
  • 1
pronebird
  • 12,068
  • 5
  • 54
  • 82