Pregunta

Estoy trabajando en portar un código antiguo (10,2 época) de archivado basado NSCoding / plist a la utilización de datos básicos. Tengo una NSOutlineView con una costumbre NSTextFieldCell. La vista de esquema está unido a un NSTreeController para proporcionar los datos.

El modelo de las consolidaciones es el siguiente:

NSTreeController: Managed Object Context -> Controller.managedObjectContext

NSTableColumn

de NSOutlineView Valor -> Controlador del árbol: arrangedObjects: itemDictionary

El NSOutlineView tiene una NSTextFieldCell subclase personalizada que agrega una imagen al lado del campo de texto, por lo que estoy pasando los valores de la NSManagedObject a ella como una NSMutableDictionary llama itemDictionary para que pueda tirar y establecer el título y isChecked valores clave.

¿Dónde estoy funcionando en problemas está actualizando el valor del campo de texto y de paso, que valor cambiado de nuevo a mi instancia de objeto gestionado. Después de que el usuario hace doble clic en el valor del título y lo edita, se pasa a -(id)objectValue, pero no estoy seguro de lo que el siguiente paso es conseguir que la actualización propaga a mi ejemplo NSManagedObject. El código que tengo hasta el momento para la lectura y los valores de ajuste en mi subclase NSTextFieldCell es el siguiente:

- (void)setStringValue:(NSString *)aString {
  [super setObjectValue:aString];
}

- (void)setObjectValue:(id <NSCopying>)anObject {  
  id cellValues = anObject;

  [super setObjectValue:[cellValues valueForKey:@"title"]];
  [self setCheckState:[[cellValues valueForKey:@"isChecked"] integerValue]];
}

- (id)objectValue {
  return [super objectValue];
}
¿Fue útil?

Solución

Pregunté por ahí, y esta es la recomendación alguien me dio; parece razonable.

En la subclase NSCell, en cualquier método es invocado por el bucle de eventos sobre el establecimiento de un nuevo valor, hacer algo como esto:

- (void)whateverMethodInCellSubclassIsTriggeredByEventLoop:(id)value {
    NSTableView *tableView = [self controlView];
    NSTableColumn *column = [[tableView tableColumns] objectAtIndex:[tableView editedColumn]];
    NSInteger rowIndex = [tableView editedRow];
    NSDictionary *bindingInfo = [column infoForBinding:NSValueBinding];
    id modelObject = nil;

    if ([controlView isKindOfClass:[NSOutlineView class]]) {
        NSTreeNode *item = [outlineView itemAtRow:rowIndex];
        modelObject = [item representedObject];
    } else if ([controlView isKindOfClass:[NSTableView class]]) {
        NSArrayController *controller = [bindingInfo objectForKey:NSObservedObjectKey];
        modelObject = [[controller arrangedObjects] objectAtIndex:rowIndex];
    }

    [modelObject setValue:value forKeyPath:[bindingInfo objectForKey:NSObservedKeyPathKey]];
}

Esto es bastante código genérico que aprovecha la información de enlace disponible en la columna de la tabla para conseguir el objeto de modelo y de ruta de la clave a la que los cambios deben ser empujados, y para uso genérico KVC para empujar los cambios. Se debe trabajar tanto para mesa y delinear vistas, así como para los objetos del modelo de datos arbitrarios, Core o no.

Otros consejos

Yo probablemente abordar esto de una manera diferente, mediante la aplicación del método delegado outlineView:willDisplayCell:forTableColumn:item:, y establecer la propiedad isChecked de la célula de allí, en vez de hacerlo desde la subclase de células. A continuación, acaba de unir esa columna directamente a arrangedObjects.title, por lo que el mecanismo de edición por defecto se encargaría de establecer la propiedad de la instancia de objeto gestionado.

IIRC, el parámetro item te pasó en realidad será una instancia NSTreeNode cuya representedObject propiedad le dará la instancia NSManagedObject para esa fila, por lo que se puede conseguir cualquier información que necesita de esa manera.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top