2011-07-13 12 views
8

He creado una aplicación que tiene un NSTableView que representa una serie de archivos. A partir de esto, quiero ser capaz de arrastrar una fila (es decir, un nombre de archivo) desde mi NSTableView al Finder, y el archivo se creará en esa carpeta. Sin embargo, el bit que no puedo resolver es que necesito modificar el contenido del archivo original, antes de que se copie al Finder.Problema con arrastrar y soltar de NSTableView a Finder

He añadido la siguiente línea para que pueda arrastrar fuera de mi NSTableView:

[self.tableView setDraggingSourceOperationMask:NSDragOperationCopy forLocal:NO];  

Y puede conseguirlo para copiar el archivo real, siempre añado una ubicación actual archivos a la mesa de trabajo, el uso de :

- (BOOL)tableView:(NSTableView *)aTableView writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard *)pboard { 
    [pboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType] owner:nil];   
    NSMutableArray* dragfiles = [[NSMutableArray alloc] init]; 
    NSString* file = [self.files objectAtIndex:row]; 
    NSString* filepath = [[[self.pathControl URL] path] stringByAppendingPathComponent:file]; 
    [dragfiles addObject:filepath]; 
    [pboard setPropertyList:dragfiles forType: NSFilenamesPboardType]; 
    [dragfiles release]; 
} 

Pero, porque quiero modificar el contenido del archivo, no quiero poner rutas de los archivos en la mesa de trabajo. He intentado usar NSFileWrapper, pero Finder no parece aceptar esto como un formato válido.

He consultado Google y he encontrado varias sugerencias de que puede crear un archivo temporal y usar esa ruta de archivo. Pero, esto se siente feo.

¿Es posible enviar datos al Finder? ¿Hay una manera de resolver esto?

Respuesta

17

Lo más probable es que desee utilizar archivos de promesa, o NSFilesPromisePboardType en lugar de NSFilenamesPboardType. (Nota: los métodos de archivo de promesa y namesOfPromisedFilesDroppedAtDestination: de los que habla la documentación son los métodos genéricos NSView. NSTableView define los métodos más convenientes que usará en lugar de los genéricos. Dicho esto, eso aún debería proporcionar información sobre cómo se prolonga el archivo de promesa trabajo). NSTableView usa tableView:namesOfPromisedFilesDroppedAtDestination:forDraggedRowsWithIndexes:, que es donde puede hacer el procesamiento de sus archivos. En su método tableView:writeRowsWithIndexes:toPasteboard:, declarará NSFilesPromisePboardType, luego establecerá una matriz de extensiones de nombre de archivo para los tipos de archivos que planea escribir. El siguiente es pseudo-código que describe cómo es posible acercarse a ella:

- (BOOL)tableView:(NSTableView *)aTableView 
    writeRowsWithIndexes:(NSIndexSet *)rowIndexes 
     toPasteboard:(NSPasteboard *)pboard { 
    [pboard declareTypes:[NSArray arrayWithObjects:NSFilesPromisePboardType, nil]]; 

    NSMutableArray *filenameExtensions = [NSMutableArray array]; 
    NSArray *draggedFilenames = [self.files objectsAtIndexes:rowIndexes]; 
    for (NSString *filename in draggedFilenames) { 
      NSString *filenameExtension = [filename pathExtension]; 
      if (filenameExtension.length) { 
       [filenameExtensions addObject:filenameExtension]; 
      } 
    } 
    [pboard setPropertyList:filenameExtensions 
       forType:NSFilesPromisePboardType]; 
    return YES; 
} 

Luego, en sus nombres-de-promisedFiles método:

- (NSArray *)tableView:(NSTableView *)aTableView 
     namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination 
     forDraggedRowsWithIndexes:(NSIndexSet *)indexSet { 

    NSArray *draggedFilenames = [self.files objectsAtIndexes:indexSet]; 

    for (NSString *filename in draggedFilenames) { 
      // do your processing of files in here 
      // if it may take a long time, you might need to do it on a background 
      // thread 

     NSString *fullPathToOriginal = nil; 
      NSString *destPath = 
     [[dropDestination path] stringByAppendingPathComponent:filename]; 


    } 
    return draggedFilenames; 
} 

Usted debe ser capaz de calcular la ruta del archivo original (no seguro de cómo lo está determinando, así que lo dejé nil en el código anterior) y la ruta del archivo de destino (usando algo como en el código anterior).

+0

Impresionante. Muchas muchas gracias. Había funcionado 5 minutos después de leer esto (después de haber pasado 3 horas tratando de obtener algo que funcionara anoche). Mi error era perder la relevancia de las extensiones de archivo para la promesa inicial. Gracias de nuevo. – RichS

+0

+1 ¡Excelente y rara respuesta! – trojanfoe

5

Algo a lo que tener cuidado.

En NSPasteboard.h hay un comentario que dice:

/* Use of pboard types should be replaced with use of UTIs. 
    Pboard types will be deprecated in a future release. */ 

Y después de la definición NSFilesPromisePboardType dice:

// Use (NSString *)kPasteboardTypeFileURLPromise 

yo pasamos un par de horas golpeando mi cabeza contra una pared de ladrillo porque estaba pasando en (NSString *)kPasteboardTypeFileURLPromise en lugar de NSFilesPromisePboardType en algunos lugares.

Parece que no hacen exactamente lo mismo. No pude averiguar por qué:

tableView:namesOfPromisedFilesDroppedAtDestination:forDraggedRowsWithIndexes 

no se estaba llamando.Cuando cambié de nuevo a NSFilesPromisePboardType,
de repente se llamó.

+4

'NSFilesPromisePboardType' espera extensiones de nombre de archivo; 'kPasteboardTypeFileURLPromise' espera URLs de archivos; 'kPasteboardTypeFilePromiseContent' (solo mencionado en Pasteboard.h, AFAIK) espera UTI. El último es el reemplazo moderno para el primero. –

+0

Gracias por estos valiosos consejos, pero ¿cómo proporciona las URL a kPasteboardTypeFileURLPromise? NSURL no es un tipo de cartón. – Nickkk