2009-07-09 1 views
19

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

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

ответ

6

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

В подклассе NSMutableDictionary имеется Cocoa With Love post, который, вероятно, будет полезен, если вы решите пойти по этому маршруту. У меня также есть created my own NSMutableDictionary subclasses, и вы можете использовать открытый код.

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

+0

Спасибо. Я думаю, что композиция вокруг NSMutableDictionary - это путь. Я до сих пор не могу понять, как сделать эту работу, если только ключи не являются NSStrings, но я думаю, что, возможно, я смогу с этим справиться. –

+0

@Quinn Taylor: ссылка на ваш пользовательский подкласс кажется мертвой, и мне нужно будет проверить этот код. Вы все еще там где-то висели? – Cyrille

6

Я успешно реализовал это сейчас, используя композицию вокруг NSMutableDictionary. Я удивлен, как мало кода он принял. Я реализовал класс, который используется для представления модели в настольной игре. Любой пользователь может подписаться на изменения на борту государств, вызвав addObserver: метод реализован так:

- (void)addObserver:(id)observer { 
    for (id key in grid) 
     [self addObserver:observer 
       forKeyPath:[key description] 
        options:0 
        context:key]; 
} 

Так как вы можете подписаться только к ключам с использованием модели Кво, я обманул и подписался на описание ключа , но передавая сам ключ как контекст. В объектах, которые наблюдают экземпляры моего Совета, я реализую -observeValueForKeyPath:ofObject:change:context:, чтобы игнорировать строку keyPath и просто использовать контекст переданный.

Мой простой класс платы не соответствует требованиям 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 с нестрочными ключами!

+0

Подписываться описанию - хороший трюк! –