Pregunta

¿Qué tengo que hacer para actualizar un tableView unido a un NSArrayController cuando se llama a un método que actualiza la matriz subyacente? Un ejemplo puede aclarar esto.

Cuando mis inicia la aplicación, se crea un SubwayTrain. Cuando se inicializa SubwayTrain, se crea un solo SubwayCar. SubwayCar tiene una matriz mutable 'pasajeros'. Cuando se inicializa un vagón de metro, se crea la matriz pasajeros, y un par de personas objetos se ponen en (digamos que una persona con el nombre "revisor", y otro, llamado "vagabundo"). Estos chicos están siempre en el SubwayCar así que los creo en la inicialización y añadir a la matriz pasajeros.

Durante la vida de las personas de aplicaciones bordo del vehículo. 'AddPassenger' se llama en la SubwayCar, con la persona que se pasa como un argumento.

Tengo una NSArrayController obligado a subwayTrain.subwayCar.passengers, y en el lanzamiento de mi revisor y vagabundo presento bien. Pero cuando se utiliza [subwayCar addPassenger:], la tableView no se actualiza. He confirmado que el pasajero es, sin duda añadido a la matriz, pero nada se actualiza en la interfaz gráfica de usuario.

¿Qué soy yo probabilidades de estar haciendo mal? Mi instinto es que está relacionado con MVA - el Controlador de array no sabe a actualizar cuando se llama addPassenger (a pesar de que addPassenger llama [pasajeros addObject:].. ¿Qué podría estar recibiendo mal aquí - me pueden enviar el código si ayuda

Gracias a cualquiera que esté dispuesto a ayudar.

Actualizar

Por lo tanto, resulta que puedo conseguir que esto funcione, cambiando por el método de addPassenger

[seatedPlayers addObject:person];

a

NSMutableSet *newSeatedPlayers = [NSMutableSet setWithSet:seatedPlayers];

[newSeatedPlayers addObject:sp];

[seatedPlayers release];

[self setSeatedPlayers:newSeatedPlayers];

Creo que esto se debe a que estoy usando [setSeatedPlayers auto]. ¿Esta es la manera correcta de hacerlo? Parece muy engorroso para copiar la matriz, liberar la antigua, y actualizar la copia (en lugar de sólo la adición a la matriz existente).

¿Fue útil?

Solución

  

Por lo tanto, resulta que puedo conseguir que esto funcione, cambiando por el método de addPassenger

[seatedPlayers addObject:person];
     

a

NSMutableSet *newSeatedPlayers = [NSMutableSet setWithSet:seatedPlayers];
[newSeatedPlayers addObject:sp];
[seatedPlayers release];
[self setSeatedPlayers:newSeatedPlayers];
     

Creo que esto se debe a que estoy usando [self setSeatedPlayers]. Es esta la forma correcta de hacerlo?

En primer lugar, es setSeatedPlayers:, con el colon. Eso es de vital importancia en Objective-C.

El uso de sus propios definidores es la forma correcta de hacerlo, pero usted está utilizando la forma correcta incorrecta. Funciona, pero aún se está escribiendo más código que es necesario.

Lo que debe hacer es poner en práctica métodos de acceso establecidos, tales como addSeatedPlayersObject:. A continuación, enviarse a sí mismo ese mensaje. Esto hace que la gente añadiendo un corto de una sola línea:

[self addSeatedPlayersObject:person];

Y mientras usted sigue los formatos de descriptor de acceso KVC conformes , recibirá notificaciones MVA de forma gratuita, tal como lo hace con setSeatedPlayers:.

Las ventajas de este sobre setSeatedPlayers: son:

  • Su código de mutar el conjunto será más corto.
  • Debido a que es más corto, que será más limpio.
  • Uso de descriptores de acceso específicos puesta a punto de mutación proporciona la posibilidad de configuración específica de mutación notificaciones MVA, en lugar de en general notificaciones del-whole-Dang-set-cambiado.

También prefiero esta solución sobre mutableSetValueForKey:, tanto por razones de brevedad y porque es tan fácil de escribir mal la llave en esa cadena literal. ( Uli Kusterer tiene una macro para causar una advertencia cuando eso sucede , que es útil cuando usted realmente necesita hablar con KVC o el propio MVA.)

Otros consejos

No sé si es considerado un error, pero addObject: (y RemoveObject: atIndex :) no genero notificaciones MVA, por lo que la vista del controlador de matriz / tabla no está siendo actualizado. Para ser compatible con MVA, utilice mutableArrayValueForKey:

Ejemplo:

[[self mutableArrayValueForKey:@"seatedPlayers"] addObject:person];

También querrá aplicar InsertObject: inSeatedPlayersAtIndex: desde el default métodos MVA son muy lento (que crean un conjunto completamente nuevo, agregar el objeto a esa matriz, y establecer la matriz original a la nueva matriz - muy ineficiente )

- (void)insertObject:(id)object inSeatedPlayerAtIndex:(int)index
{
   [seatedPlayers insertObject:object atIndex:index];
}

Tenga en cuenta que este método también se llamará cuando el controlador de array añade objetos, por lo que también es un buen gancho para piensa como el registro de una operación de deshacer, etc.

No he probado esto, así que no puedo decir que funciona, pero no os obtener notificaciones MVA llamando

  

InsertObject: atArrangedObjectIndex:

en el ArrayController?

La clave de la magia de Valor llave Observando se encuentra en clave Valor cumplimiento . Inicialmente estaba utilizando un nombre de método addObject: que sólo se asocia con el "patrón de acceso no ordenada" y su propiedad era una propiedad indexada (NSMutableArray). Cuando hayas cambiado de propiedad a una propiedad no ordenada (NSMutableSet) funcionó. Considere NSArray o NSMutableArray a ser indexados y propiedades NSSet o NSMutableSet sean propiedades desordenadas. Usted realmente tiene que leer esta sección cuidadosamente para saber lo que se requiere para hacer que la magia sucede ... valor-clave-cumplimiento. Hay algunos métodos 'necesaria' para las diferentes categorías, incluso si usted no tiene intención de utilizarlos.

  1. Uso willChangeValueForKey: y didChangeValueForKey: envueltos alrededor de un cambio de un miembro cuando el cambio no parece causar una notificación de MVA. Esto es muy útil cuando se cambia directamente una variable de instancia.

  2. Uso willChangeValueForKey:withSetMutation:usingObjects: y didChangeValueForKey:withSetMutation:usingObjects: envueltos alrededor de un cambio del contenido de una colección cuando el cambio no parece causar una notificación de MVA.

  3. Utilice [seatedPlayers setByAddingObject:sp] para hacer las cosas más cortos y de no sobrecargar innecesariamente la asignación de conjunto mutable.

En general, lo haría bien esto:

[self willChangeValueForKey:@"seatedPlayers"
            withSetMutation:NSKeyValueUnionSetMutation 
               usingObjects:sp];
[seatedPlayers addObject:sp];
[self didChangeValueForKey:@"seatedPlayers" 
           withSetMutation:NSKeyValueUnionSetMutation 
              usingObjects:sp];

o esto:

[self setSeatedPlayers:[seatedPlayers setByAddingObject:sp]];

con la última alternativa causando una invocación automática de las funciones enumeradas bajo 1. En primer lugar alternativa debería ser mejor rendimiento.

scroll top