In primo luogo, è necessario comprendere che KVO è di osservazione di un oggetto per i cambiamenti nella proprietà. Cioè, non è possibile "osservare un array" in quanto tale, si osserva una proprietà di raccolta indicizzata. Quella proprietà può essere supportata da un array o implementata in altro modo. Fintanto che è conforme a KVC e modificato in modo conforme a KVO, è sufficiente. (Quindi, non importa se la proprietà è di tipo NSArray*
o implementato utilizzando una o niente NSMutableArray*
.)
Quindi, si sta osservando un esempio di Model
per i cambiamenti nella sua proprietà items
. Se si desidera che l'osservatore per ottenere una notifica di modifica, è necessario assicurarsi di modificare sempre la proprietà items
in maniera KVO-compliant.
Il modo migliore, a mio parere, è l'attuazione del mutable indexed collection accessors e sempre usare quelli per modificare la proprietà. Quindi, si sarebbe implementare almeno uno di questi:
- (void) insertObject:(id)anObject inItemsAtIndex:(NSUInteger)index;
- (void) insertItems:(NSArray *)objects atIndexes:(NSIndexSet *)indexes;
E uno di questi:
- (void) removeObjectFromItemsAtIndex:(NSUInteger)index;
- (void) removeItemsAtIndexes:(NSIndexSet *)indexes;
Quando la proprietà è supportato da un NSMutableArray
, i metodi di cui sopra sono involucri semplici intorno ai metodi corrispondenti su _items
.
Eventuali altri metodi che scrivete per modificare la vostra proprietà dovrebbe passare attraverso uno di quelli. Così, il vostro metodo di -addItem:
sarebbe:
- (void)addItem:(Item *)item {
[self insertObject:item inItemsAtIndex:[_items count]];
}
si potrebbe anche togliere il getter pianura per la proprietà items
e invece solo esporre i getter di raccolta indicizzati:
- (NSUInteger) countOfItems;
- (id) objectInItemsAtIndex:(NSUInteger)index;
che non è necessario, però, se ci è un tipico getter.
(L'esistenza di queste funzioni di accesso è quello che consente di implementare una proprietà a-molti che non è di tipo NSArray
. Non c'è bisogno, dal punto di vista di KVC, per qualsiasi interfaccia attuale array tipizzato.)
Personalmente, non lo consiglio, ma una volta che si dispone di tali accessor, è possibile anche mutare la proprietà ottenendo il proxy NSMutableArray
-like per la proprietà utilizzando -mutableArrayValueForKey:
e quindi inviando le operazioni di mutazione ad esso. Quindi, in questo caso, potresti fare [[self mutableArrayValueForKey:@"items"] addObject:item]
. Non mi piace perché ritengo che la codifica del valore-chiave valga quando la chiave è data.È dinamico o memorizzato in un file di dati come un NIB, non noto al momento della compilazione. I nomi delle chiavi hard-coding quando hai la possibilità di usare un simbolo di lingua (ad es. Selettore) per indirizzare la proprietà è un odore di codice.
Può essere giustificato, tuttavia, per operazioni che sono veramente tortuose da implementare in termini di accessorie indicizzate, come l'ordinamento.
Infine, è possibile utilizzare -willChange...
e -didChange...
metodi del protocollo NSKeyValueObserving
per emettere le notifiche di modifica quando si modifica direttamente archiviazione secondaria della struttura senza passare attraverso un metodo di mutazione che KVO in grado di riconoscere e gancio in. Per una proprietà di raccolta indicizzata, sarebbero i metodi -willChange:valuesAtIndexes:forKey:
e -didChange:valuesAtIndexes:forKey:
. Questo è un odore di codice ancora peggiore, per quanto mi riguarda.
Puoi pubblicare quale codice hai scritto finora? – Holly
Inoltre, dovresti probabilmente controllare [questo] (http://stackoverflow.com/questions/3478451/key-value-observing-with-an-nsarray) post. – Holly
La domanda duplicata sembra mettere l'array mutabile nell'intestazione, è comunque necessario per eseguire questa operazione senza fornire l'accesso pubblico per la modifica della matrice in questione? –