在 NSTokenField 中放置一个令牌
Dropping a token in NSTokenField
我正在实现一个应用程序,可以将 NSTableView
中的行拖放到 NSTokenField
中,但我正在努力实现交互的放置端。我有 subclassed NSTokenField
(如下面的调试代码所示)。但我只看到对 draggingEntered:
和 updateDraggingItemsForDrag:
方法的调用。即使我 return 一个有效的 NSDragOperation
(Copy
),NSDraggingDestination
中的其他方法的 none 也会被调用。在令牌字段上移动时,光标短暂闪烁到复制图标,但随后 returns 变为正常光标。
出于调试目的,我尝试实现与 NSDraggingDestination
关联的所有方法,如下面的代码所示。是否有另一个 class 或 NSTokenField
的一部分正在处理掉落?是否可以覆盖它?
我已确认粘贴板确实包含有效粘贴板类型的数据。
let kPasteboardType = "SamplePasteboardType"
class MyTokenField : NSTokenField
{
override func draggingEntered(sender: NSDraggingInfo) -> NSDragOperation {
// entered
NSLog("ENTERED")
// must come from same window
guard self.window == sender.draggingDestinationWindow() else {
return super.draggingEntered(sender)
}
// has valid pasteboard data?
let pb = sender.draggingPasteboard()
if let _ = pb.dataForType(kPasteboardType) {
NSLog("MATCHED")
return NSDragOperation.Copy
}
return super.draggingEntered(sender)
}
override func draggingUpdated(sender: NSDraggingInfo) -> NSDragOperation {
NSLog("UPDATED")
// must come from same window
guard self.window == sender.draggingDestinationWindow() else {
return super.draggingUpdated(sender)
}
// has valid pasteboard data?
let pb = sender.draggingPasteboard()
if let _ = pb.dataForType(kPasteboardType) {
return NSDragOperation.Copy
}
return super.draggingUpdated(sender)
}
override func draggingExited(sender: NSDraggingInfo?) {
NSLog("EXITED")
super.draggingExited(sender)
}
override func prepareForDragOperation(sender: NSDraggingInfo) -> Bool {
NSLog("PREPARE")
return super.prepareForDragOperation(sender)
}
override func performDragOperation(sender: NSDraggingInfo) -> Bool {
NSLog("PERFORM")
return super.performDragOperation(sender)
}
override func concludeDragOperation(sender: NSDraggingInfo?) {
NSLog("CONCLUDE")
super.concludeDragOperation(sender)
}
override func draggingEnded(sender: NSDraggingInfo?) {
NSLog("ENDED")
super.draggingEnded(sender)
}
override func updateDraggingItemsForDrag(sender: NSDraggingInfo?) {
// super.updateDraggingItemsForDrag(sender)
guard let drag = sender else {
return
}
let classes: [AnyClass] = [NSPasteboardItem.self]
let options: [String: AnyObject] = [NSPasteboardURLReadingContentsConformToTypesKey: [kPasteboardType]]
drag.enumerateDraggingItemsWithOptions(NSDraggingItemEnumerationOptions.ClearNonenumeratedImages, forView: self, classes: classes, searchOptions: options) {
(item, idx, stop) in
NSLog("\(item)")
}
}
}
感谢@stevesliva 的评论,我得以解决问题。我发现了一些关键注意事项(它们可能部分是由于我对粘贴板和 drag/drop 交互的无知)。
Subclass NSTokenField
class 是没有必要的。
我必须为令牌字段实现委托函数tokenField(tokenField: NSTokenField, readFromPasteboard pboard: NSPasteboard) -> [AnyObject]?
。
我不得不更改拖动的开始位置以将字符串值存储到粘贴板。似乎如果粘贴板没有字符串值,则永远不会调用上面的委托函数。
我正在实现一个应用程序,可以将 NSTableView
中的行拖放到 NSTokenField
中,但我正在努力实现交互的放置端。我有 subclassed NSTokenField
(如下面的调试代码所示)。但我只看到对 draggingEntered:
和 updateDraggingItemsForDrag:
方法的调用。即使我 return 一个有效的 NSDragOperation
(Copy
),NSDraggingDestination
中的其他方法的 none 也会被调用。在令牌字段上移动时,光标短暂闪烁到复制图标,但随后 returns 变为正常光标。
出于调试目的,我尝试实现与 NSDraggingDestination
关联的所有方法,如下面的代码所示。是否有另一个 class 或 NSTokenField
的一部分正在处理掉落?是否可以覆盖它?
我已确认粘贴板确实包含有效粘贴板类型的数据。
let kPasteboardType = "SamplePasteboardType"
class MyTokenField : NSTokenField
{
override func draggingEntered(sender: NSDraggingInfo) -> NSDragOperation {
// entered
NSLog("ENTERED")
// must come from same window
guard self.window == sender.draggingDestinationWindow() else {
return super.draggingEntered(sender)
}
// has valid pasteboard data?
let pb = sender.draggingPasteboard()
if let _ = pb.dataForType(kPasteboardType) {
NSLog("MATCHED")
return NSDragOperation.Copy
}
return super.draggingEntered(sender)
}
override func draggingUpdated(sender: NSDraggingInfo) -> NSDragOperation {
NSLog("UPDATED")
// must come from same window
guard self.window == sender.draggingDestinationWindow() else {
return super.draggingUpdated(sender)
}
// has valid pasteboard data?
let pb = sender.draggingPasteboard()
if let _ = pb.dataForType(kPasteboardType) {
return NSDragOperation.Copy
}
return super.draggingUpdated(sender)
}
override func draggingExited(sender: NSDraggingInfo?) {
NSLog("EXITED")
super.draggingExited(sender)
}
override func prepareForDragOperation(sender: NSDraggingInfo) -> Bool {
NSLog("PREPARE")
return super.prepareForDragOperation(sender)
}
override func performDragOperation(sender: NSDraggingInfo) -> Bool {
NSLog("PERFORM")
return super.performDragOperation(sender)
}
override func concludeDragOperation(sender: NSDraggingInfo?) {
NSLog("CONCLUDE")
super.concludeDragOperation(sender)
}
override func draggingEnded(sender: NSDraggingInfo?) {
NSLog("ENDED")
super.draggingEnded(sender)
}
override func updateDraggingItemsForDrag(sender: NSDraggingInfo?) {
// super.updateDraggingItemsForDrag(sender)
guard let drag = sender else {
return
}
let classes: [AnyClass] = [NSPasteboardItem.self]
let options: [String: AnyObject] = [NSPasteboardURLReadingContentsConformToTypesKey: [kPasteboardType]]
drag.enumerateDraggingItemsWithOptions(NSDraggingItemEnumerationOptions.ClearNonenumeratedImages, forView: self, classes: classes, searchOptions: options) {
(item, idx, stop) in
NSLog("\(item)")
}
}
}
感谢@stevesliva 的评论,我得以解决问题。我发现了一些关键注意事项(它们可能部分是由于我对粘贴板和 drag/drop 交互的无知)。
Subclass
NSTokenField
class 是没有必要的。我必须为令牌字段实现委托函数
tokenField(tokenField: NSTokenField, readFromPasteboard pboard: NSPasteboard) -> [AnyObject]?
。我不得不更改拖动的开始位置以将字符串值存储到粘贴板。似乎如果粘贴板没有字符串值,则永远不会调用上面的委托函数。