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;
}
Gracias, agradezco la respuesta. Todavía estoy realmente sorprendido de que sea tan complicado hacer un seguimiento de las filas reorganizadas. – livings124
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
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. –