Search code examples
ioscocoa-touchkey-value-observing

Why do KVO observers see an empty NSKeyValueChangeNewKey when observing an unordered to-many relationship?


There is a property on a UIViewController subclass that changes when a view becomes visible. (A set stops being empty.) I've implemented KVC/KVO as follows:

- (void)viewWillAppear:(BOOL)animated {
    [self willChangeValueForKey:@"anticipatedIndexPaths" withSetMutation:NSKeyValueSetSetMutation usingObjects:_anticipatedIndexPaths];

    [super viewWillAppear:animated];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    assert([_anticipatedIndexPaths count]);
    [self didChangeValueForKey:@"anticipatedIndexPaths" withSetMutation:NSKeyValueSetSetMutation usingObjects:_anticipatedIndexPaths];
}

A subclass of that class is observing itself for @"anticipatedIndexPaths", but the value of NSKeyValueChangeNewKey when observing NSKeyValueChangeReplacement is always an empty set. What gives?


Solution

  • Got it. Two things:

    First, at least for unordered to-many relationships, the KVO infrastrucure records the value of your property on the willChange-: call. On didChange-:, it passes only the given set minus the previous value. Second, on viewWillAppear:, even before the [super viewWillAppear:] call, hidden == NO.

    In my case, this meant by property was returning the non-empty set. The result of KVO's subtraction was the empty set.