Во-первых, вы должны понимать, что КВО для наблюдения объекта изменения в его свойствах. То есть вы не можете «наблюдать массив» как таковой, вы наблюдаете свойство индексированной коллекции. Это свойство может быть подкреплено массивом или реализовано каким-то другим способом. До тех пор, пока он совместим с KVC и модифицируется в соответствии с KVO-совместимым способом, этого достаточно. (Таким образом, это не имеет значения, если свойство имеет тип NSArray*
или реализован с использованием или что-нибудь NSMutableArray*
.)
Итак, вы наблюдаете экземпляр Model
изменений в его собственности items
. Если вы хотите, чтобы наблюдатель получил уведомление об изменении, вы всегда должны изменить свойство items
с соблюдением KVO.
Лучшим способом, на мой взгляд, является реализация mutable indexed collection accessors и всегда использовать его для изменения свойства. Таким образом, вы бы реализовать хотя бы одну из них:
- (void) insertObject:(id)anObject inItemsAtIndex:(NSUInteger)index;
- (void) insertItems:(NSArray *)objects atIndexes:(NSIndexSet *)indexes;
И один из них:
- (void) removeObjectFromItemsAtIndex:(NSUInteger)index;
- (void) removeItemsAtIndexes:(NSIndexSet *)indexes;
Когда свойство опирается на NSMutableArray
, эти методы являются простые обертки вокруг соответствующих методов на _items
.
Любые другие методы, которые вы пишете для изменения вашей собственности, должны проходить через один из них. Таким образом, ваш метод -addItem:
будет:
- (void)addItem:(Item *)item {
[self insertObject:item inItemsAtIndex:[_items count]];
}
Можно также удалить простой поглотитель для items
собственности и вместо того, чтобы только выставить индексированные добытчик коллекции:
- (NSUInteger) countOfItems;
- (id) objectInItemsAtIndex:(NSUInteger)index;
В этом нет необходимости, хотя, если есть является типичным геттером.
(Существование этого аксессораха является то, что позволяет реализовать свойство ко многим, что не типа NSArray
. Там нет необходимости, с точкой КЦА зрения, для любого фактического массива типизированного интерфейса.)
Лично я не рекомендую это, но как только у вас есть такие аксессоры, вы также можете изменить свойство, получив NSMutableArray
-прокси-сервер для этого свойства, используя -mutableArrayValueForKey:
, а затем отправив ему мутационные операции. Итак, в этом случае вы можете сделать [[self mutableArrayValueForKey:@"items"] addObject:item]
. Мне это не нравится, потому что я считаю, что ключевое значение кодируется, когда ключ является данными.Он динамический или хранится в файле данных, таком как NIB, который неизвестен во время компиляции. Имена жесткого кодирования, если у вас есть возможность использовать символ языка (например, селектор) для обращения к свойству, являются запахом кода.
Это может быть оправдано, однако, для операций, которые действительно извилисты для реализации с точки зрения индексированных аксессуаров, таких как сортировка.
Наконец, вы можете использовать протокол NSKeyValueObserving
в -willChange...
и -didChange...
методы испускать уведомления об изменениях, когда вы непосредственно изменить хранилище подпирают свойства, не проходя через метод мутации, что КВО может распознавать и зацепить. Для свойства индексированной коллекции это будут методы -willChange:valuesAtIndexes:forKey:
и -didChange:valuesAtIndexes:forKey:
. Насколько мне известно, этот запах еще хуже.
Можете ли вы разместить код, который вы написали? – Holly
Кроме того, вам следует, вероятно, просмотреть сообщение [this] (http://stackoverflow.com/questions/3478451/key-value-observing-with-an-nsarray). – Holly
Дублирующий вопрос, кажется, помещает изменяемый массив в заголовок, есть ли все равно для достижения этого, не предоставляя публичный доступ к мутированию рассматриваемого массива? –