2011-12-31 11 views
6

Tengo problemas para utilizar la nueva funcionalidad Lion para reorganizar filas en mi aplicación. Estoy usando outlineView:pasteboardWriterForItem: para almacenar los índices de fila para que pueda acceder a ellos más tarde cuando valide/acepte el drop. Creo un nuevo NSPasteboardItem para volver, y estoy tratando de almacenar el número de fila como tan:reorganizando las filas de la tabla arrastrando en Lion

[pbItem setData: [NSKeyedArchiver archivedDataWithRootObject: [NSNumber numberWithInteger: [fTableView rowForItem: item]]] 
                forType: TABLE_VIEW_DATA_TYPE]; 

TABLE_VIEW_DATA_TYPE es una cadena personalizada que estoy usando para distinguir mis datos personalizados en la mesa de trabajo arrastrando. No lo uso fuera de arrastrar estas filas.

Al intentar el arrastre, que recibo en la consola: 'TableViewDataType' is not a valid UTI string. Cannot set data for an invalid UTI.

Por supuesto que podría utilizar algunos de los incorporados en las infecciones urinarias de mesas de trabajo, pero ninguna de ellas se aplica (y su uso provoca el arrastre de aceptar arrastra a otra que las filas, que no debería). ¿Hay algo que me falta, como una forma de definir una UTI personalizada solo para arrastrar (sin convertirla en una UTI "real", ya que no tengo uso para ella fuera del arrastre interno, por lo que no debería ser pública).

¡Gracias por cualquier ayuda!

Respuesta

2

En lugar de utilizar un vainilla NSPasteboardItem, debe crear un objeto personalizado que cumpla con el protocolo NSPasteboardWriting.

En su objeto personalizado, puede implementar writableTypesForPasteboard: para devolver una lista de UTI personalizadas que admita su artículo. A continuación, implementa pasteboardPropertyListForType: para devolver una representación plist de su objeto para la UTI personalizada adecuada cuando la mesa de trabajo lo solicite.

Puede crear un plist a partir de datos arbitrarios usando el método +propertyListWithData:options:format:error: de NSPropertyListSerialization.

Sobreescribiría tableView:pasteboardWriterForRow: en el origen de datos de la vista de tabla para devolver una instancia de su objeto personalizado.

+1

Gracias, agradezco la respuesta. Todavía estoy realmente sorprendido de que sea tan complicado hacer un seguimiento de las filas reorganizadas. – livings124

+0

Implementé un objeto que se ajusta a 'NSPasteboardWriting' que devuelve mi UTI personalizada para' writableTypesForPasteboard: ', pero obtengo: _'TableViewDataType 'no es una cadena UTI válida. No se puede usar una UTI no válida como un tipo devuelto por -writeableTypesForPasteboard: en la clase TableViewDragNode._ – livings124

+0

Si ese es el caso, entonces no creo que tenga otra opción que declarar una UTI personalizada para sus operaciones de arrastre en Info.plist. Estoy de acuerdo, esto parece ser una limitación extraña. No creo que sea posible definir una UTI en tiempo de ejecución, debe estar codificada en Info.plist. –

5

Otra técnica que puede utilizar es simplemente almacenar los índices de los objetos que está arrastrando en una variable de instancia en el costado. Poner todo en la mesa de trabajo no es estrictamente necesario a menos que acepte elementos de otra aplicación o viceversa.

  1. En awakeFromNib, regístrese para NSStringPboardType.
  2. En ... pasteboardWriterForRow, devuelve [NSString string].
  3. En ... arrastrandoSesión: willBegin ..., establezca su variable de instancia en los índices que desea rastrear.
  4. En validateDrop, devuelva NSDragOperationNone si la variable de instancia es nula o la vista no es suya.
  5. En ... arrastrandoSesión: finalizado ..., nula la variable de instancia.

Espero que ayude ... Estoy utilizando la técnica para una vista de tabla, pero debe ser prácticamente idéntica para una vista de esquema.

6

Tenía requisitos similares, excepto que tenía una grilla de objetos que quería reorganizar arrastrando los objetos seleccionados a una nueva ubicación.Hay varias maneras de hacerlo, incluida la creación de un objeto personalizado y la implementación de los protocolos NSPasteboardWriting y NSPasteboardReading, (y los protocolos NSCoding si va a leer datos como NSPasteboardReadingAsKeyedArchive), pero esto parece ser excesivo para arrastrar objetos que permanecen internos al solicitud.

Lo que hice involucró el uso del NSPasteboardItem como un contenedor con un tipo de UTI personalizado (ya implementa los protocolos NSPasteboardWriting y NSPasteboardReading). En primer lugar declarar una medida Tipo UTI:

#define kUTIMyCustomType @“com.mycompany.MyApp.MyCustomType”

Esto tiene que ser definido en el formato ‘com.domain.MyApp’ de lo contrario se producirán errores de la forma: “XXX no es una cadena válida UTI. No se pueden establecer datos para una UTI no válida. "Apple menciona esto en su documentación.

Luego debe registrar este tipo de UTI personalizado en la vista en la que se realizará el arrastre. Esto se puede hacer en tiempo de ejecución y no requiere adiciones de .plist. En el método init de su vista, agregue el siguiente:

[self registerForDraggedTypes:[NSArray arrayWithObjects:(NSString *)kUTIMyCustomType, nil]]; 

Ahora, asegúrese de que el delegado se establece para este punto de vista, y el objeto delegado implementa los NSDraggingSource y NSDraggingDestination conocer los protocolos requeridos. Esto le permitirá evitar romper el patrón de diseño de MVC, al permitir que el objeto de controlador designado maneje la colocación de los datos en la mesa de trabajo, lo que probablemente implique consultar los datos del modelo (es decir, índices).

En concreto, para la puesta en el arrastre de la mesa de trabajo los índices de los objetos que ser trasladado al arrastrar comienza como NSPasteboardItem envoltorios de los datos de índice:

- (void) draggingSession:(NSDraggingSession *)session willBeginAtPoint:(NSPoint)screenPoint 
{ 
    NSPasteboard * pboard = [NSPasteboard pasteboardWithName:NSDragPboard]; 
    [pboard clearContents]; 

    NSMutableArray * selectedIndexes = [NSMutableArray array]; 

    // Add NSString indexes for dragged items to pasteboard in NSPasteboardItem wrappers. 
    for (MyModel * myModel in [self selectedObjects]) 
    { 
     NSPasteboardItem * pasteboardItem = [[[NSPasteboardItem alloc] init] autorelease]; 
     [pasteboardItem setString:[NSString stringWithFormat:@"%@", [myModel index]] 
         forType:kUTIMyCustomType]; 
     [selectedIndexes addObject:pasteboardItem]; 
    } 

    [pboard writeObjects:selectedIndexes]; 
} 

Y cuando la operación de arrastrar completa, para leer el índice arrastrado NSPasteboardItem datos:

- (BOOL) performDragOperation:(id <NSDraggingInfo>)sender 
{ 
    NSPasteboard * pasteboard = [sender draggingPasteboard]; 

    // Check for custom NSPasteboardItem's which wrap our custom object indexes. 
    NSArray * classArray = [NSArray arrayWithObject:[NSPasteboardItem class]]; 
    NSArray * items = [pasteboard readObjectsForClasses:classArray options:[NSDictionary dictionary]]; 

    if (items == nil) 
     return NO; 

    // Convert array of NSPasteboardItem's with NSString index reps. to array of NSNumber indexes. 
    NSMutableArray * indexes = [NSMutableArray array]; 
    for (NSPasteboardItem * item in items) 
     [indexes addObject:[NSNumber numberWithInteger:[[item stringForType:kUTIMyCustomType] integerValue]]]; 

    // 
    // Handle dragged indexes… 
    // 

    return YES; 
} 
Cuestiones relacionadas