Наблюдение за изменениями 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 с помощью нестрочных ключей!