Cocoa NSTextField Drag&丢弃需要子类......真的吗?

时间:2011-01-08 22:34:46

标签: cocoa drag-and-drop cocoa-bindings nsview

直到今天,我还没有机会使用除NSWindow之外的任何东西作为NSDraggingDestination。当使用窗口作为一个通用的拖拽目的地时,NSWindow会将这些消息传递给它的委托,允许你处理drop而不用子类化NSWindow。

docs说:

  

尽管NSDraggingDestination是   宣布为非正式协议   NSWindow和NSView是你的子类   创建只需要采用协议   实现那些方法   相关。 (NSWindow和NSView   课程提供私人   所有的实现   方法。)一个窗口对象或   其代表可以实施这些   方法;但是,代表的   如果实现优先   两者都有实现   地方。

今天,我有一个窗口,上面有两个NSTextFields,我希望它们具有不同的放置行为,我不想让窗口中的任何其他位置掉落。我解释文档的方式,似乎我要么必须子类化NSTextField,要么在窗口的委托上制作一些巨大的意大利面条件下拉处理程序,它们针对每个视图点击检查draggingLocation以选择不同的drop - 每个领域的区域行为。

基于NSWindow-delegate的集中式丢弃处理程序方法似乎在任何情况下都会繁琐,因为您只有少量的drop目标视图。同样,无论如何,子类化方法似乎都很繁琐,因为现在丢弃处理代码存在于视图类中,所以一旦你接受了丢弃,你就必须想出一些方法来将丢弃的数据编组回到模型。 bindings docs通过以编程方式设置UI值来警告您尝试驱动绑定。所以,现在你也不得不回到原点。

所以我的问题是:"真的!?这些是唯一随时可用的选择吗?或者我在这里错过了一些直截了当的东西?"

感谢。

1 个答案:

答案 0 :(得分:6)

经过一番研究后,似乎“是的,真的,你的两个选择要么是NSTextField的子类,要么使用你的NSWindowDelegate来处理丢弃。”我会更进一步,并声称两者的更好的方式,对于花园种类的情况,“我想在一个窗口中的多个放置区”是使用NSWindowDelegate方法与命中检查,因为你避免了问题在视图端有你的丢弃处理代码。我最终在我的窗口委托类中使用了这个draggingUpdated:方法:

- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender
{
    NSPasteboard *pboard = [sender draggingPasteboard];
    NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];

    if ([pboard.types containsObject: NSFilenamesPboardType] && (sourceDragMask & NSDragOperationCopy))
    {
        NSView* hitView = [sender.draggingDestinationWindow.contentView hitTest: sender.draggingLocation];
        if (hitView && (hitView == mSourceTextField || hitView == mDestTextField))
        {
            return NSDragOperationCopy;            
        }
    }

    return NSDragOperationNone;
}

显然整体情况还有更多,但这种基于hitTest:的方法到目前为止对我有用。我怀疑如果使用基于多个NSCell的控件(如NSTableView或NSOutlineView),这会稍微复杂一些,但不出所料,那些都有自己的拖动处理方法。

希望这有助于其他人。