5

Что нужно сделать, чтобы обновить tableView, привязанный к NSArrayController при вызове метода, который обновляет базовый массив? Пример может прояснить это.NSArrayController и KVO

Когда мое приложение запускается, оно создает SubwayTrain. Когда SubwayTrain инициализируется, он создает один SubwayCar. SubwayCar имеет изменчивый массив «пассажиров». Когда автомобиль Subway инициализируется, создается массив пассажиров, и в него добавляется несколько объектов People (скажем, человек с именем «collector»), а другой - «бездомный». Эти ребята всегда на SubwayCar, поэтому я создаю их при инициализации и добавляю их в массив пассажиров.

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

У меня есть NSArrayController, связанный с subwayTrain.subwayCar.passengers, и при запуске мой коллекционер билетов и бездомный парень выглядят хорошо. Но когда я использую [subwayCar addPassenger:], tableView не обновляется. Я подтвердил, что пассажир определенно добавлен в массив, но ничего не обновляется в gui.

Что я могу делать неправильно? Мой инстинкт заключается в том, что он связан с KVO - контроллер массива не знает, что нужно обновлять при вызове addPassenger (хотя addPassenger вызывает [passengers addObject:]. Что я могу ошибаться здесь? Я могу отправить код, если это поможет.

Благодаря тех, кто готов помочь.

UPDATE

Таким образом, получается, что я могу получить эту работу, изменив методом addPassenger из

[seatedPlayers addObject:person]; 

в

NSMutableSet *newSeatedPlayers = [NSMutableSet setWithSet:seatedPlayers]; 

[newSeatedPlayers addObject:sp]; 

[seatedPlayers release]; 

[self setSeatedPlayers:newSeatedPlayers]; 

Я думаю, что это потому, что я использую [self setSeatedPlayers]. Правильно ли это? Кажется ужасно громоздким, чтобы скопировать массив, выпустить старый и обновить копию (в отличие от просто добавления существующего массива).

+0

Как вид таблицы связан с контроллером? У вас есть столбец таблицы, привязанный к свойству 'subwayTrain.subwayCar.passengers' (например, имя столбца привязано к' subwayTrain.subwayCar.passengers.name')? – outis

+0

yep точно. И имена пассажиров появляются, когда они запускаются. –

ответ

1

Таким образом, получается, что я могу получить эту работу, изменив методом addPassenger из

[seatedPlayers addObject:person]; 

в

NSMutableSet *newSeatedPlayers = [NSMutableSet setWithSet:seatedPlayers]; 
[newSeatedPlayers addObject:sp]; 
[seatedPlayers release]; 
[self setSeatedPlayers:newSeatedPlayers]; 

Я думаю, это потому, что я использую [self setSeatedPlayers]. Правильно ли это?

Прежде всего, это setSeatedPlayers:, с двоеточием. Это жизненно важно в Objective-C.

Использование собственных устройств - это правильный способ сделать это, но вы используете неправильный правильный путь. Он работает, но вы все еще пишете больше кода, чем вам нужно.

Что вам нужно сделать, это реализовать набор аксессуаров, например addSeatedPlayersObject:. Затем отправьте это сообщение. Это делает добавление людей короткий Однострочник:

[self addSeatedPlayersObject:person]; 

И до тех пор, пока вы следуете the KVC-compliant accessor formats, вы получите Кво уведомления бесплатно, так же, как вы делаете с setSeatedPlayers:.

Преимущества этого над setSeatedPlayers: являются:

  • Ваш код мутировать набор будет короче.
  • Потому что он короче, он будет чище.
  • Использование определенных атрибутов set-mutation предоставляет возможность определенных уведомлений KVO, связанных с множеством мутаций, вместо общих уведомлений об изменении целого dang-set.

Я также предпочитаю это решение за mutableSetValueForKey:, как для краткости, так и потому, что так легко пропустить ключ в этом строковом литерале. (Uli Kusterer has a macro to cause a warning when that happens, что полезно, когда вам действительно нужно поговорить с КВЦ или сам КВО.)

7

Я не знаю, если его считать ошибкой, но addObject: (и removeObject: atIndex :) не генерируют уведомления KVO, поэтому представление контроллера массива/таблицы не обновляется. Чтобы быть КВО-совместимый, используйте mutableArrayValueForKey:

Пример:

[[self mutableArrayValueForKey:@"seatedPlayers"] addObject:person]; 

Вы также хотите реализовать insertObject: inSeatedPlayersAtIndex: так как по умолчанию методы КВО действительно медленно (они создают совершенно новый массив, добавить объект этого массива, и установить исходный массив в новый массив - очень неэффективный)

- (void)insertObject:(id)object inSeatedPlayerAtIndex:(int)index 
{ 
    [seatedPlayers insertObject:object atIndex:index]; 
} 

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

1

Я не пробовал, так что я не могу сказать, что это работает, но не вы бы получать уведомления КВО по телефону

insertObject: atArrangedObjectIndex:

на ArrayController?

+0

Да, используя NSArrayController для мутации массива, он делает так, чтобы NSArrayController знал о мутации, и он (и связанные с ней вещи) должен соответствующим образом обновлять. – ipmcc

0
  1. Использование willChangeValueForKey: и didChangeValueForKey: обернут вокруг смены элемента, когда изменение не появляется, чтобы вызвать уведомление КВО. Это пригодится, когда вы напрямую меняете переменную экземпляра.

  2. Используйте willChangeValueForKey:withSetMutation:usingObjects: и didChangeValueForKey:withSetMutation:usingObjects:, обернутые вокруг изменения содержимого коллекции, когда изменение не вызывает уведомления KVO.

  3. Используйте [seatedPlayers setByAddingObject:sp], чтобы сделать вещи короче и избежать ненужного выделения изменяемого набора.

В целом, я бы сделал это либо:

[self willChangeValueForKey:@"seatedPlayers" 
      withSetMutation:NSKeyValueUnionSetMutation 
       usingObjects:sp]; 
[seatedPlayers addObject:sp]; 
[self didChangeValueForKey:@"seatedPlayers" 
      withSetMutation:NSKeyValueUnionSetMutation 
       usingObjects:sp]; 

или это:

[self setSeatedPlayers:[seatedPlayers setByAddingObject:sp]]; 

с последней альтернативой вызываю автоматический вызов функций, перечисленные в разделе 1. Первой альтернативы должен быть лучше.

1

Ключ от магии Key Value Observing находится в Key Value Compliance. Сначала вы использовали имя метода addObject: которое связано только с «неупорядоченным шаблоном доступа», и ваше свойство было индексированным свойством (NSMutableArray). Когда вы изменили свое свойство на неупорядоченное свойство (NSMutableSet), оно сработало. Рассмотрим NSArray или NSMutableArray для индексирования свойств, а NSSet или NSMutableSet - неупорядоченные свойства. Вам действительно нужно внимательно прочитать этот раздел, чтобы узнать, что требуется для совершения волшебства ... Key-Value-Compliance. Существуют некоторые методы «Обязательные» для разных категорий, даже если вы не планируете их использовать.

 Смежные вопросы

  • Нет связанных вопросов^_^