objective-c - 通过在 Lion 中拖动来重新排列表格行

标签 objective-c macos cocoa nstableview nsoutlineview

我在使用新的 Lion 功能重新排列应用程序中的行时遇到问题。我正在使用 outlineView:pasteboardWriterForItem: 来存储行索引,以便稍后在验证/接受放置时可以访问它们。我创建了一个新的 NSPasteboardItem 来返回,并尝试这样存储行号:

[pbItem setData: [NSKeyedArchiver archivedDataWithRootObject: [NSNumber numberWithInteger: [fTableView rowForItem: item]]]
                                                     forType: TABLE_VIEW_DATA_TYPE];

TABLE_VIEW_DATA_TYPE 是我用来区分拖动粘贴板中的自定义数据的自定义字符串。除了拖动这些行之外,我不使用它。

尝试拖动时,我在控制台中收到:'TableViewDataType' 不是有效的 UTI 字符串。无法为无效的 UTI 设置数据。

当然,我可以将一些内置的 UTI 用于粘贴板,但它们都不适用(并且使用它们会导致拖动接受行以外的拖动,这是不应该的)。有没有我遗漏的东西,比如定义一个自定义 UTI 只是为了拖动的方法(没有让它成为“真正的”UTI,因为我在内部拖动之外没有用它,所以它不应该公开)。

感谢您的帮助!

最佳答案

我有类似的要求,只是我有一个对象网格,我想通过将所选对象拖动到新位置来重新排列这些对象。有几种方法可以做到这一点,包括创建自定义对象和实现 NSPasteboardWritingNSPasteboardReading 协议(protocol)(以及 NSCoding 协议(protocol),如果你愿意的话)以 NSPasteboardReadingAsKeyedArchive) 的形式读取数据,但这对于拖动保留在应用程序内部的对象来说似乎有点矫枉过正。

我所做的涉及使用 NSPasteboardItem 作为自定义 UTI 类型的包装器(它已经实现了 NSPasteboardWritingNSPasteboardReading 协议(protocol))。首先声明一个自定义的 UTI 类型:

#define kUTIMyCustomType @“com.mycompany.MyApp.MyCustomType”

这需要以“com.domain.MyApp”格式定义,否则您将收到以下形式的错误:“XXX 不是有效的 UTI 字符串。无法为无效的 UTI 设置数据。” Apple 在他们的文档中提到了这一点。

然后您必须在将发生拖动的 View 中注册此自定义 UTI 类型。这可以在运行时完成,不需要任何 .plist 添加。在您的 View 的 init 方法中添加以下内容:

[self registerForDraggedTypes:[NSArray arrayWithObjects:(NSString *)kUTIMyCustomType, nil]];

现在,确保为此 View 设置了委托(delegate),并且委托(delegate)对象实现了所需的NSDraggingSourceNSDraggingDestination 协议(protocol)方法。这将允许您通过允许指定的 Controller 对象处理将数据放置在可能涉及查询模型数据(即索引)的粘贴板上来避免破坏 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;
}

关于objective-c - 通过在 Lion 中拖动来重新排列表格行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8685832/

相关文章:

iphone - 在二进制中查找类符号的来源

objective-c - 在我的 xib 文件中委托(delegate)给文件所有者是什么意思?

xcode - 使用 Storyboard更改 NSWindow 大小

objective-c - 获取 NSMutableDictionary 中的键出现在弹出按钮中

Objective-C cocoa 应用程序覆盖 JSON 文件

cocoa - 获取 NSPasteboardTypeFileURL 的 UTI

ios - collectionview 单元格之间的不规则空间

iOS 指定初始化器 : Using NS_DESIGNATED_INITIALIZER

MacOsX : ScreenSaver -- how to get the path to . 保护程序包

objective-c - 从 NSArray 创建 NSMutableArray 的最有效方法