直到今天,我还没有机会使用除NSWindow之外的任何东西作为NSDraggingDestination。当使用窗口作为一个通用的拖拽目的地时,NSWindow会将这些消息传递给它的委托,允许你处理drop而不用子类化NSWindow。
docs说:
尽管NSDraggingDestination是 宣布为非正式协议 NSWindow和NSView是你的子类 创建只需要采用协议 实现那些方法 相关。 (NSWindow和NSView 课程提供私人 所有的实现 方法。)一个窗口对象或 其代表可以实施这些 方法;但是,代表的 如果实现优先 两者都有实现 地方。
今天,我有一个窗口,上面有两个NSTextFields,我希望它们具有不同的放置行为,我不想让窗口中的任何其他位置掉落。我解释文档的方式,似乎我要么必须子类化NSTextField,要么在窗口的委托上制作一些巨大的意大利面条件下拉处理程序,它们针对每个视图点击检查draggingLocation以选择不同的drop - 每个领域的区域行为。
基于NSWindow-delegate的集中式丢弃处理程序方法似乎在任何情况下都会繁琐,因为您只有少量的drop目标视图。同样,无论如何,子类化方法似乎都很繁琐,因为现在丢弃处理代码存在于视图类中,所以一旦你接受了丢弃,你就必须想出一些方法来将丢弃的数据编组回到模型。 bindings docs通过以编程方式设置UI值来警告您尝试驱动绑定。所以,现在你也不得不回到原点。
所以我的问题是:"真的!?这些是唯一随时可用的选择吗?或者我在这里错过了一些直截了当的东西?"
感谢。
答案 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),这会稍微复杂一些,但不出所料,那些都有自己的拖动处理方法。
希望这有助于其他人。