2010-02-19 16 views
16

Estoy intentando entender el mecanismo de clave-valor de codificación (KVC) de Cocoa un poco mejor. He leído el número Key-Value Programming Guide de Apple, pero todavía estoy un poco confundido acerca de cómo ciertos métodos KVC buscan claves. Particularmente, mutableArrayValueForKey:.¿Cuál es el patrón de búsqueda de KVC para mutableArrayValueForKey?

A continuación explicaré cómo entiendo valueForKey: KVC "getters" para trabajar. Luego, llegaré a mi pregunta sobre mutableArrayValueForKey.


Hay siete diferentes "getter" métodos 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 búsqueda de un valor dentro de una propiedad (llamado myKey), documentos de Apple estado que valueForKey: búsquedas como esta :

  1. Tries -getMyKey, -myKey y -isMyKey (en ese orden) dentro del receptor
  2. Si no lo encuentra, intenta estos pidió, a varios captadores (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. A continuación, intenta estos, captadores desordenadas-a-muchos (NSSet) :

    - (NSUInteger)countOfMyKey; 
    - (NSEnumerator *)enumeratorOfMyKey; 
    - (KeyClass *)memberOfMyKey:(KeyClass *)anObject; 
    
  4. a continuación, los intentos de acceso directamente variables de instancia, suponiendo YES es devuelto por accessInstanceVariablesDirectly, en este orden: _myKey, _isMyKey, myKey, isMyKey.

  5. Por último, se da por vencido y llama al método - (id)valueForUndefinedKey:(NSString *)key de la clase receptora. Por lo general, un error se plantea aquí.


Mi pregunta es, ¿cuál es el patrón de orden de búsqueda de mutableArrayValueForKey :?

Apple's docs state this:

Accessor Patrón de búsqueda para Ordenadas Colecciones

El patrón de búsqueda por defecto para mutableArrayValueForKey: es como sigue:

clase del receptor se buscó un par de métodos cuyos nombres coinciden con los patrones -insertObject: inAtIndex: y -removeObjectFromAtIndex: (correspondientes a los métodos primitivos NSMutableArray InsertObject: atIndex: y removeObjectAtIndex: respectivamente), o métodos que coincida con el patrón -Insertar : atIndexes: y -removeAtIndexes: (correspondiente a las NSMutableArrayinsertObjects: atIndexes : y removeObjectsAtIndexes: methods). Si al menos un método de inserción y se encuentran al menos un método de eliminación de cada mensaje enviado a NSMutableArray el objeto de colección proxy resultado en alguna combinación de -insertObject: inAtIndex :, -removeObjectFromAtIndex :, -Insertar: atIndexes: y -removeAtIndexes: mensajes que se envían al receptor original de mutableArrayValueForKey :. ... etc ...

Esto no tiene sentido para mí ya que se trata de métodos tipo "setter". mutableArrayValueForKey: devuelve un NSMutableArray. Todos los métodos enumerados anteriormente devuelven el vacío y se utilizan para editar un NSMutableArray, no para obtenerlo. Ejemplo:

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

Alguna idea de lo que Apple está tratando de decir en sus documentos, o si esto es quizás un error?

Mi teoría es que mutableArrayValueForKey: es probable que tome una ruta similar a valueForKey: al buscar recuperar un valor de KVC. Simplemente no estoy seguro de qué camino es realmente.

¡Gracias por cualquier ayuda que pueda ofrecer! :)

Respuesta

21

El NSMutableArray regrese de llamar mutableArrayValueForKey: es en realidad una subclase particular de NSMutableArray que anula métodos de arreglos normales, como -count, -objectAtIndex:, -insertObject:atIndex:, etc., y llama a los métodos KVC correspondientes en el objeto de la matriz fue recuperado de . Básicamente, actúa como un proxy para manipular la relación de muchos del objeto, y no es algo de lo que deba preocuparse por crear o devolver usted mismo. Un ejemplo rápido de uso:

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

Esta pieza de código añade una pista al principio de la lista de reproducción. Si la clase Playlist implementa los métodos KVC para su relación "tracks", llamar a un método en la matriz mutable dará como resultado que se llame al método apropiado sobre el objeto subyacente. Por lo tanto, en este ejemplo, cuando llama al insertObject:atIndex: en la matriz, la matriz llamará al insertObjectInTracks:atIndex: en el objeto de la lista de reproducción y la pista se agregará a la matriz de pistas de la lista de reproducción.

Ahora, en este ejemplo, por supuesto, puede simplemente llamar al insertObjectInTracks:atIndex: directamente, pero hay varias ventajas que puede obtener al usar mutableArrayValueForKey:.

  • El contenedor de matriz oculta los detalles de implementación de los métodos de KVC subyacentes. No es estrictamente necesario implementar la lista completa de métodos para cumplir con KVC. La clase Playlist podría implementar -tracks y -setTracks:, y el código anterior seguirá funcionando. En este caso, en lugar de llamar al insertObjectInTracks:atIndex:, el proxy de matriz mutable creará una nueva matriz con el objeto insertado al principio, y luego simplemente llamará al setTracks: en el objeto Playlist. Obviamente, esto es menos eficiente, por lo que generalmente se recomienda implementar la lista completa de métodos de KVC.
  • En el caso en que, en lugar de una cadena constante para la clave, tiene una variable en su lugar, usar mutableArrayValueForKey: le permite manipular la relación sin tener que conocer los nombres exactos de los métodos que tiene que llamar. Siempre que el objeto cumpla con KVC para la clave que está utilizando, todo "solo funcionará".
  • También le permite usar cualquier método que NSMutableArray implemente, así que, por ejemplo, podría usar métodos que busquen en la matriz objetos, ordene la matriz, etc. sin tener que reescribir versiones especiales para tratar con el material de KVC.
+0

Gracias Brian, eso fue extremadamente útil. :) –

+1

"Este fragmento de código agrega una pista al comienzo de la lista de reproducción", creo que agrega una pista al comienzo de las pistas, ¿no de la lista de reproducción? –

+0

es relevante decir que este enfoque es relevante cuando se usan enlaces. En el ejemplo anterior, si la lista de reproducción es un NSArrayController vinculado a la matriz de pistas y tenemos un NSTableView vinculado a este controlador, para que los cambios en las pistas se reflejen en la tabla a través del controlador de matriz, debemos obtener pistas de la variable array proxy y luego agregar/eliminar objetos en esta pista: de hecho, estas operaciones reflejarán los comandos de KVC que dispararán el mecanismo de enlace. – viggio24

Cuestiones relacionadas