我需要在我的应用程序的两个表视图之间拖动对NSManagedObject的引用。存储对NSManagedObject的引用的首选NSPasteboard类型是什么?
我目前的解决方案是将对象的NSManagedObjectID的URIRepresentation存储在NSPasteboardTypeString中。我怀疑那里有更优雅的解决方案。
答案 0 :(得分:3)
所有模型对象都没有标准类型,因为模型对象及其处理方式对于您的应用程序是唯一的。如果所有人都有一种粘贴板类型,则不会分开它们。您自己的自定义对象应该有自己的拖动类型。
只需使用一个有意义的字符串(可能是#define,因此您可以在Xcode中使用自动完成找到它),例如解析为“com.yourcompany.yourapp.yourobjecttype”的“MyObjectPboardType”。
使用NSPasteboard的-declareTypes:owner:声明新类型,然后使用-setString:forType:或其他-set?:forType:方法之一来设置对象类型的信息。在您的情况下,使用对象ID是一个完全可以接受的标识符。只需记住托管对象的对象ID在新对象持久时就会发生变化。
答案 1 :(得分:1)
如果要在同一个应用程序中的表中拖动,您可以在tableView(outlineView)中的对象中添加rowIndexes(如果是从outlineView拖动的indexPaths)。如果tableViews的dataSource是NSArrayController(用于outlineView的NSTreeController),这可能会使您免于一些不必要的CoreData访问。 然后,您可以在接受拖放时轻松检索拖动的对象,因为'info'对象传递给两个方法'tableView:validateDrop:proposedRow:proposedDropOperation:'和'tableView:acceptDrop:row:dropOperation:'将引用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
}