【问题标题】:Subclassed NSView to notify ViewController of action子类化 NSView 以通知 ViewController 动作
【发布时间】:2021-08-29 16:16:10
【问题描述】:

我已将 NSView 子类化以接收一个已删除的文件夹以获取其 URL。 我通过访问我的自定义 NSView 类中设置的属性来获取我的 ViewController 类的 URL。

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
    }
    
}

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

【问题讨论】:

    标签: swift macos drag-and-drop nsview


    【解决方案1】:

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

    首先,在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)")
        }
    }
    

    【讨论】:

    • 谢谢!除了解决我的迫切需要之外,它还有助于填补我对闭包的理解。
    • 我需要在我的 init 函数中以某种方式初始化 dropSuccessfully 吗?我想我开始考虑一般的闭包(定义和调用),但我将如何初始化一个闭包?
    • @psb 不需要在你的 init 函数中初始化droppedSuccessfully,因为它是一个可选的((URL) -> Void)?。请注意末尾的? - 默认情况下,它将自动为nil。但是,如果你想初始化它,当然可以。你的初始化看起来像init(droppedURL: URL, droppedSuccessfully: @escaping ((URL) -> Void)) { self.droppedURL = droppedURL; self.droppedSuccessfully = droppedSuccessfully }
    • 经过更多调查后,我才明白这一点。再次,非常感谢。我发现闭包不是很直观,但我慢慢地围绕着它们。你的回答真的帮了我这个忙。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多