Тип NSPasteboard для NSManagedObject
Мне нужно перетащить ссылку на NSManagedObject между двумя табличными представлениями моего приложения. Какой предпочитаемый тип NSPasteboard для хранения ссылки на NSManagedObject?
Мое текущее решение состоит в том, чтобы сохранить URIR представление объекта NSManagedObjectID в NSPasteboardTypeString. Я подозреваю, что есть более элегантное решение.
2 ответа
Не существует стандартного типа для всех объектов модели, поскольку объекты модели и способ их обработки являются уникальными для вашего приложения. Если бы был один тип картона для всех, то не было бы их рассказывать отдельно. Ваш собственный объект должен иметь свой собственный тип перетаскивания.
Просто используйте строку, которая имеет смысл (возможно, #define, чтобы вы могли найти ее с автозаполнением в XCode), например "MyObjectPboardType", которая разрешается в "com.yourcompany.yourapp.yourobjecttype".
Используйте -declareTypes: owner: в NSPasteboard, чтобы объявить ваш новый тип, затем используйте -setString:forType: или один из других -set?: ForType: методы, чтобы установить информацию для типа вашего объекта. В вашем случае использование идентификатора объекта является вполне приемлемым идентификатором. Просто помните, что идентификаторы объектов управляемых объектов меняются, когда они новые и сохраняются.
Если вы перетаскиваете внутри таблиц в одном и том же приложении, вы можете также поместить в монтажный стол rowIndexes (indexPaths в случае, если вы перетаскиваете из outlineView) объектов в tableView (outlineView). Это также может избавить вас от ненужного доступа к CoreData, если источником данных tableViews является NSArrayController (NSTreeController для outlineView). Затем вы можете легко получить перетаскиваемые объекты при принятии отбрасывания, поскольку объект 'info' передал обоим методам 'tableView: validateDrop: предложил Row: saidDropOperation:' и to '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
}