2010-02-19 13 views
16

Ich versuche, Cocoa Key-Value Coding (KVC) Mechanismus ein wenig besser zu verstehen. Ich habe Apples Key-Value Programming Guide gelesen, bin aber immer noch etwas verwirrt darüber, wie bestimmte KVC-Methoden nach Schlüsseln suchen. Insbesondere mutableArrayValueForKey:.Was ist das KVC-Suchmuster für mutableArrayValueForKey?

Im Folgenden werde ich erklären, wie ich valueForKey: KVC "Getters" zu arbeiten verstehen. Dann komme ich zu meiner Frage bezüglich mutableArrayValueForKey.


Es gibt sieben verschiedene "Getter" KVC Methoden:

- (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; 

Wenn für einen Wert innerhalb eines Property Suche (benannt myKey), in den Apple docs sagen, dass ValueForKey: Suchanfragen wie diese :

  1. Tries -getMyKey, -myKey und -isMyKey (in dieser Reihenfolge) innerhalb des Empfängers
  2. Wenn nicht gefunden, versucht er, diese bestellt haben, zu viele 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. Als nächstes es versucht, diese ungeordnete, zu viele Getter (NSSet) :

    - (NSUInteger)countOfMyKey; 
    - (NSEnumerator *)enumeratorOfMyKey; 
    - (KeyClass *)memberOfMyKey:(KeyClass *)anObject; 
    
  4. Als nächstes versucht es Instanzvariablen direkt zuzugreifen, YES unter der Annahme von accessInstanceVariablesDirectly, in dieser Reihenfolge zurückgegeben: _myKey, _isMyKey, myKey, isMyKey.

  5. Schließlich gibt es auf und ruft die - (id)valueForUndefinedKey:(NSString *)key Methode der empfangenden Klasse auf. Normalerweise wird hier ein Fehler ausgelöst.


Meine Frage ist, was ist die Suchreihenfolge Muster für mutableArrayValueForKey :?

Apple's docs state this:

Accessor Suchmuster für Bestellen Kollektionen

Die Standard-Suchmuster für mutableArrayValueForKey: als folgen:

Der Empfänger Klasse für ein Paar gesucht von Methoden, deren Namen den Mustern -insertObject: inAtIndex: 01 entsprechenund -removeObjectFromAtIndex: (entsprechend den NSMutableArray primitiven Methoden insertobject: atIndex: und removeObjectAtIndex: jeweils) oder Verfahren das Muster -insert einstimmt, gefunden atIndexes: und -removeAtIndexes: (entsprechend den NSMutableArrayinsertObjects: atIndexes : und removeObjectsAtIndexes: Methoden). Wenn mindestens ein Einfügungsverfahren und mindestens ein Entfernungsverfahren jede NSMutableArray Nachricht gesendet die Sammlung proxy Objekt Ergebnis in einer Kombination aus -insertObject gefunden: inAtIndex :, -removeObjectFromAtIndex :, -insert: atIndexes: und -removeAtIndexes: Nachrichten, die an den ursprünglichen Empfänger von mutableArrayValueForKey: gesendet werden. ... etc ...

Das macht für mich keinen Sinn, da es "Setter" wie Methoden diskutiert. mutableArrayValueForKey: gibt ein NSMutableArray zurück. Alle oben aufgelisteten Methoden geben void zurück und werden verwendet, um ein NSMutableArray zu bearbeiten, jedoch nicht. Beispiel:

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

Jede Idee, was Apple in ihre docs sagen will, oder ob dies vielleicht ein Fehler?

Meine Theorie ist, dass mutableArrayValueForKey: wahrscheinlich einen ähnlichen Pfad wie valueForKey: bei der Suche nach einem KVC-Wert zu nehmen. Ich bin mir nicht sicher, welcher Weg das wirklich ist.

Danke für jede Hilfe, die Sie anbieten können! :)

Antwort

21

Die NSMutableArray Sie zurück mutableArrayValueForKey: Aufruf ist eigentlich eine private Unterklasse von NSMutableArray die normalen Array Methoden wie -count überschreibt, -objectAtIndex:, -insertObject:atIndex: usw. und ruft die entsprechenden KVC Methoden für das Objekt wurde das Array abgerufen aus . Es dient im Grunde als Proxy für die Manipulation der Zu-Viele-Beziehung des Objekts, und es ist nicht etwas, worüber man sich sorgen muss, wenn man sich selbst erstellt oder zurückgibt. Ein schnelles Anwendungsbeispiel:

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

Dieser Codeabschnitt fügt einen Titel am Anfang der Wiedergabeliste hinzu. Wenn die Playlist-Klasse KVC-Methoden für ihre "Spuren" -Beziehung implementiert, führt das Aufrufen einer Methode für das veränderbare Array dazu, dass die entsprechende Methode für das zugrunde liegende Objekt aufgerufen wird. Wenn Sie also in diesem Beispiel insertObject:atIndex: für das Array aufrufen, ruft das Array wiederum insertObjectInTracks:atIndex: für das Wiedergabelistenobjekt auf, und die Spur wird dem Spur-Array der Wiedergabeliste hinzugefügt.

Nun könnten Sie natürlich in diesem Beispiel insertObjectInTracks:atIndex: direkt anrufen, aber es gibt mehrere Vorteile, die Sie stattdessen mit mutableArrayValueForKey: bekommen können.

  • Der Array-Wrapper verbirgt die Implementierungsdetails der zugrunde liegenden KVC-Methoden. Die Implementierung der gesamten Methodenliste ist nicht unbedingt KVC-konform. Die Playlist-Klasse könnte einfach -tracks und -setTracks: implementieren, und der obige Code wird weiterhin funktionieren. In diesem Fall erstellt der veränderbare Array-Proxy anstelle des Aufrufs insertObjectInTracks:atIndex: ein neues Array mit dem Objekt, das am Anfang eingefügt wurde, und ruft dann einfach setTracks: für das Objekt Playlist auf. Dies ist offensichtlich weniger effizient, daher wird die Implementierung der vollständigen Liste der KVC-Methoden empfohlen.
  • In dem Fall, in dem statt einer konstanten Zeichenfolge für den Schlüssel stattdessen eine Variable vorhanden ist, können Sie mit mutableArrayValueForKey: die Beziehung bearbeiten, ohne die genauen Namen der Methoden kennen zu müssen, die Sie aufrufen müssen. Solange das Objekt KVC-konform für den von Ihnen verwendeten Schlüssel ist, wird alles "einfach funktionieren".
  • Sie können auch jede Methode verwenden, die NSMutableArray selbst implementiert, so können Sie zum Beispiel Methoden verwenden, die das Array nach Objekten durchsuchen, das Array sortieren usw., ohne spezielle Versionen neu schreiben zu müssen.
+0

Danke Brian, das war sehr hilfreich. :) –

+1

"Dieses Stück Code fügt einen Track am Anfang der Playlist hinzu." Ich denke, es fügt einen Track am Anfang der Tracks hinzu, nicht Playlist? –

+0

Es ist wichtig zu sagen, dass dieser Ansatz relevant ist, wenn Bindungen verwendet werden. Wenn im obigen Beispiel die Wiedergabeliste ein NSArrayController ist, der an das Spuren-Array gebunden ist, und wir eine NSTableView an diesen Controller gebunden haben, müssen Änderungen an Spuren über den Array-Controller in der Tabelle widergespiegelt werden Array-Proxy und dann Hinzufügen/Entfernen von Objekten auf dieser Spur: Infact diese Operationen spiegeln KVC-Befehle wider, die den Bindungsmechanismus auslösen werden. – viggio24