Непонятный баг при добавлении наблюдателя с помощью NSKeyValueObservingOptionInitial

У меня есть объект пользовательского интерфейса (подкласс 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… реализован? Пробовали ли вы воспроизвести проблему в минимально воспроизводимом примере?

Willeke 02.09.2024 09:19
+keyPathsForValuesAffecting... не реализовано. Я могу попытаться написать минимальный пример, но боюсь, что проблема не проявится, поскольку она возникает только тогда, когда наблюдаемый объект принадлежит к определенному подклассу, а не когда он принадлежит к другому подклассу с теми же атрибутами.
jeanlain 02.09.2024 13:56

Хорошо, проблема возникает, когда наблюдаемый объект не был «реализован» (ошибка) до того, как он был обнаружен. Если доступ к какому-либо атрибуту осуществляется до наблюдения, проблема не возникает.

jeanlain 02.09.2024 20:55
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Хорошо, я нашел причину. Проблема в том, что наблюдаемый объект был неисправностью.

Инструкция наблюдения с использованием NSKeyValueObservingOptionInitial вызывает срабатывание ошибки, что приводит к изменению других (наблюдаемых) атрибутов (полученных из хранилища), вызывая уведомления об изменениях.

Идите дальше, здесь не на что смотреть.

Другие вопросы по теме