How do i get the information from the observationInfo method in Objective C KVO?
Asked Answered
S

4

3

There is the observationInfo method which returns information of bindings of an object. I have looked around but i do not know how to get the information from the dictionary. Can any one lead me in the right direction please?

EDIT In case any one misunderstand that im saying. My classes are already all KVO compliant. Now after you add the observer to a something object, self.something will now have binding information. If i did [self.something observationInfo], this returns a dictionary. I would like to access the contents of that dictionary.

Apple docs said

For improved performance, this method and setObservationInfo: can be overridden to store the opaque data pointer in an instance variable. Overrides of this method must not attempt to send Objective-C messages to the stored data, including retain and release.

So i know that it can be done.. my question is how? I see no info any where on line.

Slacken answered 11/7, 2013 at 16:40 Comment(2)
i think you can only get description of the NSKeyValueObservationInfo like NSString* str = [NSString stringWithFormat: @"%@", [obj observationInfo]]; and then parse.Debra
seriously? :( that dictionary has pointers to the binded object and the bind context memory addresses. I have to parse the text? I edited the question aboveSlacken
B
8

I suspect you're misunderstanding the purpose of -observationInfo/-setObservationInfo:. The value that is set and gotten by those methods is opaque to you. Put differently, its contents are private to the system frameworks and you're not intended to be able to access/parse it. The comment from the docs that you excerpted was:

For improved performance, this method and setObservationInfo: can be overridden to store the opaque data pointer in an instance variable. Overrides of this method must not attempt to send Objective-C messages to the stored data, including retain and release.

Let me try to clarify what this is saying a bit:

For every observation, the frameworks need to keep track of some private data about the observation in order to deliver it later. How it stores that information is not documented, but conceptually, it's probably stored in a map where the key is the pointer value of the object and the value is this opaque data structure.

In specific, performance-sensitive situations, it may be that looking up the observation info in that shared map impacts performance significantly (I've never seen this turn up on a profiling trace myself, but that's not to say it couldn't happen). In those cases, it would be better to store the pointer directly as an instance variable in the object, which changes the fetch operation from a map-lookup to a simple add. From a system frameworks perspective, I would bet that the map-lookup cost is usually far less onerous (in the big picture) than the alternative, which would be to put an instance variable in NSObject for this purpose (which would make every object 8 bytes bigger whether it uses KVO or not -- seems like a no-brainer.)

-observationInfo/-setObservationInfo: exist to allow you to make that optimization. If you implemented this optimization, these methods would also be a way to know if your object is being observed or not (i.e. is the info value nil?) which may allow you to make other changes to your object's behavior.

If you have a need to keep a list of observing objects and details about what they're observing for some other purpose, then you will need to do that yourself by overriding addObserver:... and removeObserver:..., and adding code to maintain your own data private structures (while still calling super.)

Benghazi answered 15/7, 2013 at 14:16 Comment(0)
N
0

This worked for me.

id anObserver = self;
NSString *observerString = [anObserver description];
NSString *str = [NSString stringWithFormat: @"%@", [aController observationInfo]];
NSRange rangeOfObserver = [str rangeOfString:observerString];
if (rangeOfObserver.location == NSNotFound) {
} else {
    [aController removeObserver:anObserver forKeyPath:@"selectionIndexes" context:NULL];
}
Nucleoside answered 21/6, 2020 at 20:18 Comment(0)
L
0
id aInstance = (__bridge id)self.observationInfo;
NSArray *list = [aInstance valueForKey:@"_observances"];
for (id object in list) {
    id observer = [object valueForKey:@"_observer"];
    //id property = [object valueForKey:@"_property"];
    //NSString *keyPath = [property valueForKey:@"_keyPath"];
    NSString *keyPath = [object valueForKeyPath:@"_property._keyPath"];
    [self.stone removeObserver:observer forKeyPath:keyPath];

    NSLog(@"%@ %@", observer, keyPath);
}
Lavinalavine answered 3/2, 2021 at 8:40 Comment(1)
Please don't post only code as an answer, but also provide an explanation of what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotesReactivate
C
-1

The object you're observing must be KVO compliant. This means that you can access the relevant information from the via normal dictionary syntax. For instance:

[self.something addObserver:self
                  forKeyPath:@"cheese"
                     options:NSKeyValueObservingOptionNew
                     context:NULL];

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

  if ([keyPath isEqualToString:@"cheese"])
  {
    // Get the new key value
    [object valueForKey:keyPath];

    // See the changes for the key value
    NSLog(@"Changes: %@", change);
  }
  else
  {
    [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
  }
}

The KVO docs at Apple.

Coppage answered 11/7, 2013 at 18:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.