子类化 NSView 以通知 ViewController 操作

Subclassed NSView to notify ViewController of action

我已子classed NSView 以接收拖放的文件夹以获取其 URL。 我通过访问自定义 NSView class.

中的 属性 集,将 URL 设置为 ViewController class
import Cocoa

class DropView: NSView {
    var droppedURL : URL!

    override func draw(_ dirtyRect: NSRect) {
        super.draw(dirtyRect)

        // Drawing code here.
    }
    public required init?(coder: NSCoder) {
        super .init(coder: coder)
        registerForDraggedTypes([NSPasteboard.PasteboardType.fileURL])
    }
    
    public override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation {
        return NSDragOperation.copy
    }
    public override func draggingUpdated(_ sender: NSDraggingInfo) -> NSDragOperation {
        NSDragOperation.copy
    }
    public override func performDragOperation(_ sender: NSDraggingInfo) -> Bool {
        let pboard = sender.draggingPasteboard
        let urlString = pboard.string(forType: NSPasteboard.PasteboardType.fileURL)
        let folderURL = URL(string: urlString!)
        print(folderURL)
        droppedURL = folderURL
        return true
    }
    
}

我如何让我的 ViewController 知道何时将文件夹拖放到我的 NSView 上并且 URL 已成功捕获?除了发布通知还有其他方法吗?

通常您会为此使用 delegates or closures。我更喜欢闭包,因为它们很干净,但这取决于你。

首先,在 DropView 中定义闭包:

class DropView: NSView {
    var droppedURL : URL!
    var droppedSuccessfully: ((URL) -> Void)? /// here!

然后,像调用函数一样调用它。确保也传递您的 folderURL

public override func performDragOperation(_ sender: NSDraggingInfo) -> Bool {
    let pboard = sender.draggingPasteboard
    let urlString = pboard.string(forType: NSPasteboard.PasteboardType.fileURL)
    let folderURL = URL(string: urlString!)
    print(folderURL)
    droppedURL = folderURL
    droppedSuccessfully?(folderURL) /// here!
    return true
}

最后,将闭包分配回您的 ViewController

override func viewDidLoad() {
    super.viewDidLoad()

    ...
                                         /// prevent retain cycle
    yourDropView.droppedSuccessfully = { [weak self] url in
        print("URL received: \(url)")
    }
}