我正在实现一个应用程序,其中可以将来自NSTableView的行拖放到NSTokenField中,但我正在努力实现交互的拖放端。我已经子类化了(如下面的调试代码所示)。但我只看到对NSTokenFielddraggingEntered:方法的调用。即使我返回有效的updateDraggingItemsForDrag:NSDragOperation),也不会调用Copy中的任何其他方法。移动到令牌字段上时,光标短暂闪烁到复制图标,然后返回到正常光标。
为了调试的目的,我尝试了实现与NSDraggingDestination相关联的所有方法,如下面的代码所示。是否有其他类或NSDraggingDestination的一部分正在处理丢弃?有没有可能推翻这一点?
我已确认粘贴板确实具有有效的粘贴板类型的数据。

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的评论,我才解决了这个问题。我发现了一些关键的警告(部分原因可能是我对粘贴板和拖放交互的无知)。
不需要对NSTokenField类进行子类化。
我必须为token字段实现delegate函数。
我必须更改拖动的开始位置,以便将字符串值存储到粘贴板。似乎如果粘贴板没有字符串值,则永远不会调用上面的委托函数。

09-07 11:57