У меня есть объект пользовательского интерфейса (подкласс NSObject
, называемый Label
), который наблюдает за свойством region
(подкласс NSManagedObject
, называемым Region
) для трех основных атрибутов данных:
start
(плавать)end
(плавать)name
(NSString
)Label.m
, содержит:
-(void) setRegion:(Region *)region {
_region = region;
[region addObserver:self forKeyPath:@"start"
options:NSKeyValueObservingOptionNew
context:nil];
[region addObserver:self forKeyPath:@"end"
options:NSKeyValueObservingOptionNew
context:nil];
[region addObserver:self forKeyPath:@"name"
options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial
context:nil]; // problematic
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
NSLog(@"%@", keyPath);
}
(Я также удаляю наблюдение по мере необходимости, другим методом)
Все это кажется довольно стандартным.
Проблема в том, что когда инструкция, прокомментированная //problematic
, выполняется, observeValueForKeyPath:
вызывается 3 раза, по одному для каждого наблюдаемого ключа (start
, end
, name
), хотя проблемная инструкция наблюдает только за ключом name
(и должна отправить уведомление только один раз для этого ключа).
Использование определенного указателя для контекста каждого наблюдения не меняет этого.
Эта проблема не возникает, если проблемная инструкция размещена в начале метода или когда NSKeyValueObservingOptionInitial
добавляется в качестве опции для наблюдения за start
и end
.
Примечательно: Region
является подклассом абстрактного класса, который определяет атрибуты start
, end
и name
, и проблема не возникает, если наблюдаемый объект принадлежит другому конкретному подклассу, хотя ни один из подклассов не делает ничего особенного с этими атрибутами (они используют средства доступа по умолчанию, они не реализуют собственные установщики или что-то в этом роде).
+keyPathsForValuesAffecting...
не реализовано. Я могу попытаться написать минимальный пример, но боюсь, что проблема не проявится, поскольку она возникает только тогда, когда наблюдаемый объект принадлежит к определенному подклассу, а не когда он принадлежит к другому подклассу с теми же атрибутами.
Хорошо, проблема возникает, когда наблюдаемый объект не был «реализован» (ошибка) до того, как он был обнаружен. Если доступ к какому-либо атрибуту осуществляется до наблюдения, проблема не возникает.
Хорошо, я нашел причину. Проблема в том, что наблюдаемый объект был неисправностью.
Инструкция наблюдения с использованием NSKeyValueObservingOptionInitial
вызывает срабатывание ошибки, что приводит к изменению других (наблюдаемых) атрибутов (полученных из хранилища), вызывая уведомления об изменениях.
Идите дальше, здесь не на что смотреть.
+keyPathsForValuesAffecting…
реализован? Пробовали ли вы воспроизвести проблему в минимально воспроизводимом примере?