Наблюдение за изменениями NSMutableDictionary
Можно ли наблюдать (подписываться) на значения, хранящиеся под разными ключами в NSMutableDictionary? В моем случае ключи уже существуют, когда подписка инициируется, но значения меняются, и я хотел бы получить уведомление в этом случае. Я хотел бы получить ключ измененного значения в уведомлении.
Я предполагаю, что если мои ключи словаря были все экземпляры NSString, я мог бы просто подписаться на каждый путь ключа индивидуально. Но что, если мои ключи не являются строками? Мне повезло в этом случае?
Ответы
Ответ 1
Это интересная идея. Я не могу найти ничего в NSDictionary или NSDictionaryController, который выглядит многообещающим. Моим первым инстинктом было бы использовать композицию вокруг NSMutableDictionary и перехватывать вызовы setObject: forKey: (и, возможно, -removeObjectForKey:) для уведомления подписчиков об изменениях.
Там Cocoa С любовным сообщением о подклассе NSMutableDictionary, который, вероятно, будет полезен, если вы решите пойти по этому маршруту. У меня также есть созданный мой собственный подкласс NSMutableDictionary, и вы можете использовать открытый код.
Вы можете создать протокол наблюдателя, который мог бы указывать определенные ключи, которые следует контролировать. Не должно быть слишком много кода, но больше, чем у меня есть время бросить в данный момент.
Ответ 2
Я успешно реализовал это сейчас, используя композицию вокруг NSMutableDictionary. Я удивлен, как мало кода он принял. Я реализовал класс, который используется для представления модели в настольной игре. Любой может подписаться на изменения для состояний платы, вызвав метод addObserver:, реализованный следующим образом:
- (void)addObserver:(id)observer {
for (id key in grid)
[self addObserver:observer
forKeyPath:[key description]
options:0
context:key];
}
Поскольку вы можете подписаться только на ключи с помощью модели KVO, я обманул и подписался на описание ключа, но передал сам ключ как контекст. В объектах, которые наблюдают экземпляры моего Совета, я реализую -observeValueForKeyPath:ofObject:change:context:
, чтобы игнорировать строку keyPath и просто использовать переданный контекст.
Мой простой класс Board не соответствует KVO для искусственных свойств, которые я создаю с помощью этого метода, поэтому я прошел 0
в свойстве options
, чтобы оборудование KVO не пыталось получить старые/новые значения этих ключей, Это может привести к взрыву моего кода.
Все, что меняет плату (в моем простом классе есть только один метод, который делает это), вызывают необходимые уведомления, чтобы заставить компьютер KVO вскочить в действие:
- (void)setPiece:(id)piece atLocation:(Location*)loc {
[self willChangeValueForKey:[loc description]];
[grid setObject:piece forKey:loc];
[self didChangeValueForKey:[loc description]];
}
Voila! Подписка на NSMutableDictionary с помощью нестрочных ключей!