facebookarchive/KVOController

Unable to use action and block observers at the same time

Closed this issue · 2 comments

I can reproduce it with the following code:

[self.KVOController observe:self
                    keyPath:@"textLabel.text"
                    options:NSKeyValueObservingOptionNew
                     action:@selector(sizeToFit)];

[self.KVOController observe:self
                    keyPath:@"textLabel.text"
                    options:NSKeyValueObservingOptionNew
                      block:^(id observer, id object, NSDictionary *change) {
                          NSLog(@"change = %@", change);
                          [self sizeToFit];
                      }];

The first registered observer is called, the second one is not.

Hi,@pronebird.
From the code,

- (BOOL)isEqual:(id)object
{
  if (nil == object) {
    return NO;
  }
  if (self == object) {
    return YES;
  }
  if (![object isKindOfClass:[self class]]) {
    return NO;
  }
  return [_keyPath isEqualToString:((_FBKVOInfo *)object)->_keyPath];
}

The _FBKVOInfo class, which stores the invocation information only compares the keyPath of a specific object. So the registration of same keyPath to a block & action won't have effect the same time as the infos are stored in a NSSet.

Thus, we may need a PR to change the implementation of the isEqual method.

Hope this can help you.

grp commented

The unobserve: method takes just a key path, so KVOController uniquely identifies observations by their (object, key path) pair. As such. I'd recommend creating two KVOController instances in this case for each observation.