我有类似的要求,除了我有一个对象的网格,我想通过拖动选定的对象到一个新的位置重新排列。有这样做,包括创建一个自定义对象和实施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;
}
谢谢,欣赏响应。我仍然非常惊讶,因为跟踪重新排列的行很复杂。 – livings124 2011-12-31 16:49:17
我实现符合'NSPasteboardWriting'对象返回我的自定义UTI为'writableTypesForPasteboard:',但我发现:_'TableViewDataType”不是一个有效的UTI字符串。不能使用无效UTI从-writeableTypesForPasteboard返回类型:类TableViewDragNode._ – livings124 2012-01-01 23:32:19
如果是这样的话,那么我不认为你有任何选项,但在你的Info.plist宣布自定义UTI你拖动操作。我同意,这似乎是一个奇怪的限制。我不相信在运行时定义UTI是可能的,但它必须在Info.plist中进行硬编码。 – 2012-01-01 23:54:33