Наблюдение за изменениями NSMutableDictionary - PullRequest
19 голосов
/ 10 июля 2009

Можно ли наблюдать (подписываться) на изменения значений, хранящихся под разными ключами в NSMutableDictionary? В моем случае ключи уже существуют, когда подписка инициируется, но значения меняются, и я хотел бы получить уведомление в этом случае. Я хотел бы получить ключ от измененного значения в уведомлении.

Я предполагаю, что если бы все мои словарные ключи были экземплярами NSString, я мог бы просто подписаться на каждый путь ключа индивидуально. Но что, если мои ключи не являются строками? Мне не повезло в этом случае?

Ответы [ 2 ]

6 голосов
/ 10 июля 2009

Я успешно реализовал это сейчас, используя композицию вокруг NSMutableDictionary. Я удивлен, как мало кода потребовалось. Класс, который я реализовал, это Board, используемый для представления модели в настольной игре. Любой может подписаться на изменения в состояниях платы, вызвав метод 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 не пытался получить старые / новые значения этих ключей , Это может привести к взрыву моего кода.

Все, что меняет доску (в моем простом классе есть только один метод, который делает это), вызывает необходимые уведомления, чтобы заставить механизм КВО вступить в действие:

- (void)setPiece:(id)piece atLocation:(Location*)loc {
    [self willChangeValueForKey:[loc description]];
    [grid setObject:piece forKey:loc];
    [self didChangeValueForKey:[loc description]];
}

Вуаля! Подписка на NSMutableDictionary с нестроковыми ключами!

6 голосов
/ 10 июля 2009

Это интересная идея. Я не могу найти ничего в NSDictionary или NSDictionaryController, который выглядит многообещающим. Моим первым инстинктом было бы использовать композицию вокруг NSMutableDictionary и перехватывать вызовы setObject: forKey: (и, возможно, -removeObjectForKey :), чтобы уведомлять подписчиков об изменениях.

Есть сообщение Какао с любовью о создании подкласса NSMutableDictionary, которое, вероятно, будет полезным, если вы решите пойти по этому пути. Я также создал свои собственные подклассы NSMutableDictionary , и вы можете использовать код с открытым исходным кодом.

Вы могли бы разработать протокол наблюдателя, в котором могли бы быть указаны конкретные ключи, которые должны контролироваться. Не должно быть слишком много кода, но больше, чем у меня есть время, чтобы бросить в данный момент.

...