2010-02-19 11 views
16

Sto tentando di capire un po 'meglio il meccanismo Key-Value Coding (KVC) di Cocoa. Ho letto il numero Key-Value Programming Guide di Apple, ma sono ancora un po 'confuso su come determinati metodi KVC cercano le chiavi. In particolare, mutableArrayValueForKey:.Qual è il pattern di ricerca KVC per mutableArrayValueForKey?

Di seguito spiegherò come ho capito valueForKey: "getter" KVC per funzionare. Poi passerò alla mia domanda riguardante mutableArrayValueForKey.


Ci sono sette diversi "getter" metodi KVC:

- (id)valueForKey:(NSString *)key; 
- (id)valueForKeyPath:(NSString *)keyPath; 
- (NSDictionary *)dictionaryWithValuesForKeys:(NSArray *)keys; 
- (NSMutableArray *)mutableArrayValueForKey:(NSString *)key; 
- (NSMutableArray *)mutableArrayValueForKeyPath:(NSString *)keyPath; 
- (NSMutableSet *)mutableSetValueForKey:(NSString *)key; 
- (NSMutableSet *)mutableSetValueForKeyPath:(NSString *)keyPath; 

Durante la ricerca di un valore all'interno di una proprietà (nome myKey), documenti di Apple affermano che valueForKey: Ricerche come questo :

  1. Tenta -getMyKey, -myKey, e -isMyKey (in questo ordine) nel ricevitore
  2. Se non viene trovato, esso tenta questi ordinato, a-molti getter (NSArray):

    // Required: 
    - (NSUInteger)countOfMyKey; 
    
    // Requires At Least One: 
    - (id)objectInMyKeyAtIndex:(NSUInteger)index; 
    - (NSArray *)myKeyAtIndexes:(NSIndexSet *)indexes; 
    
    // Optional (improves performance): 
    - (void)getMyKey:(KeyClass **)buffer range:(NSRange)inRange; 
    
  3. successivo, si tenta questi non ordinati, getter a-molti (NSSet) :

    - (NSUInteger)countOfMyKey; 
    - (NSEnumerator *)enumeratorOfMyKey; 
    - (KeyClass *)memberOfMyKey:(KeyClass *)anObject; 
    
  4. successivo, si tenta di accedere direttamente variabili istanza, assumendo YES viene restituito da accessInstanceVariablesDirectly, nell'ordine: _myKey, _isMyKey, myKey, isMyKey.

  5. Infine, abbandona e chiama il metodo - (id)valueForUndefinedKey:(NSString *)key della classe ricevente. Solitamente viene generato un errore qui.


La mia domanda è, qual è il modello di ordine di ricerca per mutableArrayValueForKey :?

Apple's docs state this:

Accessor modello di ricerca per ordinati Collezioni

Il modello di ricerca predefinito per mutableArrayValueForKey: è come segue:

classe del ricevitore è cercato un paio dei metodi i cui nomi corrispondono ai modelli -insertObject: inAtIndex: e -removeObjectFromAtIndex: (corrispondente ai metodi primitivi NSMutableArray InsertObject: atIndex: e removeObjectAtIndex: rispettivamente), o metodi corrispondenti al modello -Insert : atIndexes: e -removeAtIndexes: (corrispondente ai NSMutableArrayinsertObjects: atIndexes : e removeObjectsAtIndexes: metodi). Se almeno un metodo di inserimento e almeno un metodo di rimozione si trovano ogni messaggio inviato al NSMutableArray dell'oggetto insieme proxy risultato in una combinazione di -insertObject: inAtIndex :, -removeObjectFromAtIndex :, -Insert: atIndexes: e -removeAtIndexes: messaggi inviati al ricevitore originale di mutableArrayValueForKey :. ... ecc ...

Questo non ha senso per me in quanto sta discutendo di metodi "setter". mutableArrayValueForKey: restituisce un NSMutableArray. Tutti i metodi sopra elencati sono resi nulli e vengono utilizzati per modificare un NSMutableArray, non per ottenerlo. Esempio:

- (void)insertMyKey:(KeyClass *)keyObject inMyKeyAtIndex:(NSUInteger)index; 
- (void)removeObjectFromMyKeyAtIndex:(NSUInteger)index; 

Qualche idea di cosa Apple sta cercando di dire nei propri documenti o se questo è forse un errore?

La mia teoria è che mutableArrayValueForKey: sta probabilmente prendendo un percorso simile a valueForKey: durante la ricerca per recuperare un valore KVC. Non sono sicuro di quale sia il percorso.

Grazie per l'aiuto che puoi offrire! :)

risposta

21

Il NSMutableArray si torna da chiamare mutableArrayValueForKey: è in realtà una sottoclasse privata di NSMutableArray che sostituisce i normali metodi di matrice, come -count, -objectAtIndex:, -insertObject:atIndex:, ecc e chiama i corrispondenti metodi KVC sull'oggetto l'array è stato recuperato da . Fondamentalmente agisce come un proxy per manipolare la relazione to-many dell'oggetto, e non è qualcosa che devi preoccuparti di creare o restituire te stesso. Un rapido esempio di utilizzo:

Playlist* aPlaylist; 
Track* aTrack; 
NSMutableArray* mutableTracks = [aPlaylist mutableArrayValueForKey:@"tracks"]; 
[mutableTracks insertObject:aTrack atIndex:0]; 

Questo pezzo di codice aggiunge una traccia per l'inizio della playlist. Se la classe Playlist implementa i metodi KVC per la sua relazione "tracce", quindi chiamando un metodo sull'array mutabile verrà eseguito il richiamo del metodo appropriato sull'oggetto sottostante. Quindi, in questo esempio, quando si chiama insertObject:atIndex: nell'array, la matrice chiamerà a sua volta insertObjectInTracks:atIndex: sull'oggetto playlist e la traccia verrà aggiunta alla serie di tracce della playlist.

Ora, in questo esempio, ovviamente è possibile chiamare direttamente insertObjectInTracks:atIndex:, ma ci sono diversi vantaggi che si possono ottenere usando mutableArrayValueForKey:.

  • Il wrapper di array nasconde i dettagli di implementazione dei metodi KVC sottostanti. L'implementazione dell'intero elenco di metodi non è strettamente necessaria per essere conforme a KVC. La classe Playlist potrebbe semplicemente implementare -tracks e -setTracks:, e il codice di cui sopra continua a funzionare. In questo caso, invece di chiamare insertObjectInTracks:atIndex:, il proxy matrice mutevole creerà una nuova matrice con l'oggetto inserito all'inizio, e poi semplicemente chiamare setTracks: sull'oggetto riproduzione. Questo è ovviamente meno efficiente, quindi è generalmente consigliabile implementare l'elenco completo dei metodi KVC.
  • Nel caso in cui, invece di una stringa costante per la chiave, si ha invece una variabile, utilizzando mutableArrayValueForKey: permette di manipolare il rapporto senza dover conoscere i nomi esatti dei metodi si deve chiamare. Finché l'oggetto è compatibile con KVC per la chiave che stai utilizzando, tutto "funzionerà".
  • Consente inoltre di utilizzare qualsiasi metodo implementato dallo stesso NSMutableArray, quindi ad esempio è possibile utilizzare metodi che eseguono ricerche nell'array per oggetti, ordinano l'array, ecc. Senza dover riscrivere versioni speciali per gestire il materiale KVC.
+0

Grazie Brian, che era estremamente disponibile. :) –

+1

"Questo pezzo di codice aggiunge una traccia per l'inizio della playlist", penso che aggiunge una traccia all'inizio dei brani, non playlist? –

+0

è importante dire che questo approccio è rilevante quando vengono utilizzati i binding. Nell'esempio di cui sopra, se Playlist è un NSArrayController legato alla matrice tracce e abbiamo un NSTableView vincolato a questo controller, quindi in ordine per modifiche sui brani riflettersi in tavola attraverso il controller di array, dobbiamo ottenere tracce dal mutevole array proxy e quindi aggiungi/rimuovi oggetti su questa traccia: infatti queste operazioni rifletteranno ai comandi KVC che attiveranno il meccanismo di binding. – viggio24

Problemi correlati