2010-12-12 166 views
2

我需要將引用拖到我的應用程序的兩個表視圖之間的NSManagedObject。什麼是首選的NSPasteboard類型來存儲對NSManagedObject的引用?NSManagedObject的NSPasteboard類型

我目前的解決方案是將對象的NSManagedObjectID的URIR表示存儲在NSPasteboardTypeString中。我懷疑那裏有更優雅的解決方案。

回答

3

所有模型對象都沒有標準類型,因爲您的模型對象以及它們的處理方式對於您的應用程序是唯一的。如果所有人都有一個紙板類型,那麼就不會將它們分開。您自己的自定義對象應該有自己的拖動類型。

只需使用一個合理的字符串(也許是一個#define,所以你可以在Xcode中自動完成),就像解析爲「com.yourcompany.yourapp.yourobjecttype」的「MyObjectPboardType」一樣。

使用NSPasteboard的-declareTypes:owner:聲明新的類型,然後使用-setString:forType:或另一個-set?:forType:方法來設置對象類型的信息。在你的情況下,使用對象ID是一個完全可以接受的標識符。只要記住託管對象的對象ID在新的和持久的時候就會改變。

1

如果您在同一個應用程序中的表格內拖動,您可能需要在tableView(outlineView)中的對象上粘貼rowIndexes(indexPaths,以防拖動outlineView)。如果tableViews的dataSource是NSArrayController(用於outlineView的NSTreeController),那麼這可能會讓您免於某些不必要的CoreData訪問。 然後,您可以輕鬆地檢索拖動的對象,因爲傳遞給兩個方法'tableView:validateDrop:proposedRow:proposedDropOperation:'和'tableView:acceptDrop:row:dropOperation:'的'info'對象將接受tableView在'draggingSource'鍵路徑下產生拖動。

這裏有一個簡單的實現:

extern NSString *const kMyLocalDragType = @"com.whatever.localDragType"; 
@implementation MyArrayControllerDataSource 
    . 
    . 
    . 
#pragma mark - NSTableViewDataSource (Drag & Drop) 
+ (NSArray *)dragTypes { 
    // convenience method returning all class's supported dragTypes 
    return @[kMyLocalDragType]; 
} 
- (BOOL)tableView:(NSTableView *)tableView writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard *)pboard { 
    [pboard declareTypes:[[self class] dragTypes] owner:self]; 
    for (NSString *aDragType in [[self class] dragTypes]) { 
     if (aDragType == kMyLocalDragType) { 
     NSData *data = [NSKeyedArchiver archivedDataWithRootObject:rowIndexes]; // we are supporting drag&drop of multiple items selected  
     [pboard setData:data forType:aDragType]; 
     } 
     . 
     . // logic for other dragTypes 
     . 
    } 
    return YES; 
} 
- (NSDragOperation)tableView:(NSTableView *)tableView validateDrop:(id<NSDraggingInfo>)info proposedRow:(NSInteger)row proposedDropOperation:(NSTableViewDropOperation)dropOperation { 
    NSArray *dragTypes = [info draggingPasteboard] types]; 
    for (id aDragType in dragTypes) { 
     if (aDragType == kMyLocalDragType) { 
     return NSDragOperationCopy; 
     } 
    } 
    . 
    .// Other logic for accepting drops/affect drop operation 
    . 
} 

- (BOOL)tableView:(NSTableView *)tableView acceptDrop:(id<NSDraggingInfo>)info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)dropOperation { 
    if ([info draggingPasteboard] types] containsObject:kMyLocalDragType]) { 
     // Retrieve the index set from the pasteboard: 
     NSData *data = [[info draggingPasteboard] dataForType:kMyLocalDragType]; 
     NSIndexSet *rowIndexes = [NSKeyedUnarchiver unarchiveObjectWithData:data]; 
     NSArray *droppedObjects = [self retrieveFromTableView:tableView objectsAtRows:rowIndexes]; 
     // droppedObjects contains dragged and dropped objects, do what you 
     // need to do with them, then add them to this dataSource: 
     [self.content insertObjects:droppedObjects]; 
     [tableView reloadData]; 
     [tableView deselectAll:nil]; 
     return YES; 
    } 
     . 
     . // other logic for accepting drops of other dragTypes supported. 
     . 
} 

#pragma mark - Helpers 
- (NSArray <NSManagedObject *> *)retrieveFromTableView:(NSTableView *)tableView objectsAtRowIndexes:(NSIndexSet *)rowIndexes { 
    id dataSource = [tableView dataSource]; 
    if ([dataSource respondsToSelector:@selector(content)]) { 
     if ([dataSource.content respondsToSelector:@selector(objectsAtIndexes:)]) { 
      return [datasource content] objectsAtIndexes:rowIndexes]; 
     } 
    } 
    return @[]; //We return an empty array in case introspection check failed 
} 
相關問題