0

虽然我有工作代码,但我对我是否采取了正确的方法感到困惑,我正在寻求NSPasteboard是否有人可以帮助我澄清最佳方法。

自 2012 年以来,Apple 似乎没有编写任何关于拖放的完整文档,并且在那个时候,您应该在其中实现它的方式(尤其是沙盒应用程序)似乎已经被弃用和改变。经过一番折腾,我发现当您访问它的路径属性时,拖动的粘贴板提供的文件 URL 显示了它的真实路径(而不是构成 url 的匿名数字字符串),这使得可以使用进行常规复制FileManager.

我的问题是,我在这里遵循正确的程序吗?将从NSURL粘贴板获得的内容转换为URL类型并在其中使用它copyItem(at:URL, to:URL)不起作用(即使将相同的 url 复制并粘贴到 Safari 中使我能够查看文件)。因此我改用copyItem(atPath:String, toPath:String). 为了进一步研究这一点,是否有URL替换类型的方法NSURL(from:NSPasteboard)?好像应该有。

无论如何,这是我正在工作的代码(请忽略 draggingEntered: 中的代码:目前,它只是让测试工作正常,而且我注册NSFilenamesPboardType但随后忽略它的事实也可以被忽略)。

import Cocoa

class DraggerView: NSView {
    let types = [NSURLPboardType, NSFilenamesPboardType]
    var directory:URL!

    override init(frame: NSRect) {
        super.init(frame: frame)
        register(forDraggedTypes: types)
        if  let dir = URL(string:NSTemporaryDirectory())
        {
            directory = dir
        }
    }


    required init?(coder: NSCoder) {
        super.init(coder: coder)
        register(forDraggedTypes: types)
        if  let dir = URL(string:NSTemporaryDirectory())
        {
            directory = dir
        }
    }

    override func draw(_ dirtyRect: NSRect)  {
        super.draw(dirtyRect)
        NSColor.white.set()
        NSRectFill(dirtyRect)
    }

    override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation  {
        return NSDragOperation.copy
    }


    override func performDragOperation(_ sender: NSDraggingInfo) -> Bool {

        let pboard = sender.draggingPasteboard()
        if let types = pboard.types, types.contains(NSURLPboardType) {


            // add file name to save to loaction
            if let fileURL = NSURL(from:pboard), let filename = fileURL.lastPathComponent {
                directory.appendPathComponent(filename)
                do {
                    try FileManager.default.copyItem(atPath:fileURL.path!, toPath:directory.path)
                }
                catch {
                    // something went wrong
                }
            }


            return true
        }
        else { return false }
    }
}

最后一点是,文档在注册拖动类型时一直提到使用 UTI,但我不清楚这会延伸多远。我应该用尿路感染代替NSURLPboardType和吗?NSFilenamesPboardType

4

1 回答 1

0

根据 Apple 开发者论坛上的建议,我能够放弃很多代码并实现该readObjects:方法。这大大简化了事情。

我现在可以使用以下代码(通过使用 URL 而非路径的首选方法)。

import Cocoa

class DraggerView: NSView {

    override init(frame: NSRect) {
        super.init(frame: frame)
        self.register(forDraggedTypes: [NSURLPboardType])
    }


    required init?(coder: NSCoder) {
        super.init(coder: coder)
        self.register(forDraggedTypes: [NSURLPboardType])
    }

    override func draw(_ dirtyRect: NSRect)  {
        super.draw(dirtyRect)
        NSColor.white.set()
        NSRectFill(dirtyRect)
    }



    override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation  {
       return NSDragOperation.copy
    }


    override func performDragOperation(_ sender: NSDraggingInfo) -> Bool {
        let pboard = sender.draggingPasteboard()
        if let urls = pboard.readObjects(forClasses: [NSURL.self], options: [:]) as? [URL] {
            for url in urls {
                do {
                    var directory = URL(fileURLWithPath:NSTemporaryDirectory())
                    directory.appendPathComponent(url.lastPathComponent)
                    try FileManager.default.copyItem(at:url, to:directory)
                }
                catch {
                    // something went wrong
                }

            }
        }


        return true
    }
}

注意:上面的代码将任何拖放的文件或文件夹(包括文件和子文件夹)复制到应用程序的临时目录。

于 2017-05-23T11:41:36.473 回答