У меня были аналогичные требования, за исключением того, что у меня была сетка объектов, которые я хотел переставить, перетаскивая выбранные объекты в новое место.Есть несколько способов сделать это, включая создание пользовательского объекта и реализацию протоколов NSPasteboardWriting
и NSPasteboardReading
(и протоколов NSCoding
, если вы будете читать данные как NSPasteboardReadingAsKeyedArchive
), но это кажется излишним дляперетаскивание объектов, которые остаются внутренними для приложения.
То, что я сделал, включает использование NSPasteboardItem
в качестве оболочки с пользовательским типом UTI (он уже реализует протоколы NSPasteboardWriting
и NSPasteboardReading
).Сначала объявите пользовательский тип UTI:
#define kUTIMyCustomType @“com.mycompany.MyApp.MyCustomType”
Это необходимо определить в формате 'com.domain.MyApp', в противном случае вы получите ошибки в форме: «XXX недопустимая строка UTI.Невозможно установить данные для недопустимого UTI ». Apple упоминает об этом в своей документации.
Затем необходимо зарегистрировать этот пользовательский тип UTI в представлении, в котором будет происходить перетаскивание.Это может быть сделано во время выполнения и не требует никаких дополнений .plist.В метод init вашего представления добавьте следующее:
[self registerForDraggedTypes:[NSArray arrayWithObjects:(NSString *)kUTIMyCustomType, nil]];
Теперь убедитесь, что делегат установлен для этого представления, и объект делегата реализует требуемые методы протокола NSDraggingSource
и NSDraggingDestination
.Это позволит вам избежать нарушения шаблона проектирования MVC, позволяя назначенному объекту контроллера обрабатывать размещение данных на монтажном столе, что, вероятно, потребует запроса данных модели (т. Е. Индексов).
В частности, для размещения наперетаскивающий монтажный указатель индексы объектов, которые должны быть перемещены при перетаскивании, начинается как NSPasteboardItem
оболочки ваших данных индекса:
- (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];
}
А когда операция перетаскивания завершается, для чтения перетаскиваемого индекса NSPasteboardItem
данные:
- (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;
}