Изменить значения словаря неправильно при использовании KVO с NSOperationQueue? - PullRequest
3 голосов
/ 19 ноября 2010

Я работал над примером в главе по параллелизму «Больше разработки для iPhone 3», и не могу заставить KVO на NSOperationQueue работать как положено.Я создаю NSOperationQueue и наблюдаю его массив operations, используя:

NSOperationQueue *newQueue = [[NSOperationQueue alloc] init];
self.queue = newQueue;
[newQueue release];
[queue addObserver:self
        forKeyPath:@"operations"
           options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld)
           context:NULL];

Когда в очередь добавляется первый NSOperation, я ожидаю, что он будет добавлен в базовый массив operations (документация iOS гласит, что это KVO-совместимо) и, следовательно, в словаре изменений можно найти сопоставление от NSKeyValueChangeKindKey до NSKeyValueChangeInsertion вместе с сопоставлением от NSKeyValueChangeNewKey к добавленному NSOperation.Но я не вижу никакого значения NSKeyValueChangeInsertion.

Я знаю, что отладчик профессиональный и все, но в интересах иметь что-то полезное для копирования здесь, я начал свой метод наблюдателя с:

- (void) observeValueForKeyPath:(NSString *)keyPath
                       ofObject:(id)object
                         change:(NSDictionary *)change
                        context:(void *)context {
  NSNumber *kind = [change objectForKey:NSKeyValueChangeKindKey];
  NSObject *newValue = [change objectForKey:NSKeyValueChangeNewKey];
  NSObject *oldValue = [change objectForKey:NSKeyValueChangeOldKey];
  NSIndexSet *indexes = [change objectForKey:NSKeyValueChangeIndexesKey];
  NSLog(@"kind=%d, newValue=%@, oldValue=%@, indexes=%@",
       [kind integerValue], newValue, oldValue, indexes);

И это печатает:

2010-11-18 20:01:56.249 Stalled[2692:6f07] kind=1, newValue=(
    "<SquareRootOperation: 0x5f51b40>"
), oldValue=(
), indexes=(null)

2010-11-18 20:01:56.250 Stalled[2692:6f07] kind=1, newValue=(
    "<SquareRootOperation: 0x5f51b40>"
), oldValue=(
    "<SquareRootOperation: 0x5f51b40>"
), indexes=(null)

(SquareRootOperation - это просто мой подкласс NSOperation, который соответствующим образом переопределяет main, а Stalled - просто имя проекта.)Но обратите внимание, что метод вызывается дважды при вставке одной операции, и оба раза со значением типа 1, которое равно NSKeyValueChangeSetting, а не NSKeyValueChangeInsertion.Кроме того, newValue и oldValue - это сам массив, а не добавленный элемент.

Есть идеи?Спасибо!

Ответы [ 2 ]

3 голосов
/ 23 декабря 2010

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

Не забывайте, что эти уведомления могут быть отправлены вам в любой теме!

0 голосов
/ 19 ноября 2010

Свойство операций NSOperationQueue не имеет изменяемого типа (возвращает NSArray*).Поэтому он не реализует индексированные методы соответствия многим для изменяемых массивов, поэтому вы никогда не увидите события вставки, только событие изменения для всего массива.

Edit

Shadowmatter поднял вопрос о том, что фактически возвращаемый объект - NSMutableArray.Это, однако, ничего не меняет.Во-первых, Документация Apple ясна по этому вопросу.Если объявлено, что метод возвращает неизменный объект, вы должны соблюдать API.Вы не должны использовать isKindOf:, чтобы выяснить, действительно ли оно изменчиво, и вы определенно не должны его изменять.

API говорит, что тип возвращаемого значения операций неизменен, и поэтому вы должны обращаться с ним как с таковым.Что еще более важно для этого вопроса, поскольку это не свойство изменяемой коллекции, оно не является кодирующим значение ключа для значений KVC изменяемого массива.Для соответствия изменяемой индексированной коллекции класс должен

  • Реализовать один или оба метода -insertObject:in<Key>AtIndex: или -insert<Key>:atIndexes:.
  • Реализовать один или оба метода-removeObjectFrom<Key>AtIndex: или -remove<Key>AtIndexes:.

(взято непосредственно из руководства Apple KVC)

Дизайнер класса NSOperationQueue разработал свойство operations какнеизменными и поэтому намеренно опущены вышеуказанные методы.

...