0

当此 URL 扩展作为面板运行时,它无法返回 URL,似乎绕过了完成:

func saveAs() -> URL? {
    let savePanel = NSSavePanel()
    var saveAsURL : URL? = nil

    savePanel.canCreateDirectories = true
    savePanel.nameFieldStringValue = self.lastPathComponent
    savePanel.directoryURL = FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first!

    if let keyWindow = NSApp.keyWindow {
        savePanel.beginSheetModal(for: keyWindow, completionHandler: { result in
            /*if result == .OK {*/ saveAsURL = savePanel.url //}
        })
    }
    else
    {
        NSApp.activate(ignoringOtherApps: true)

        if savePanel.runModal() == .OK {
            saveAsURL = savePanel.url
        }
    }
    Swift.print("saveAsURL => \(saveAsURL.debugDescription)")

    return saveAsURL
}

但作为独立窗口运行它工作正常。这里有另一个相关的答案但这里的用法不同:即

guard let saveAsURL = URL.init(string: "download.dmg").saveAs() else { return }

我认为用户取消会推断处理应该结束。

4

2 回答 2

0

我按照我的建议提出了什么:完成处理程序。

func saveAs(responseHandler: @escaping (URL?) -> Void) {
    let savePanel = NSSavePanel()

    savePanel.canCreateDirectories = true
    savePanel.nameFieldStringValue = self.lastPathComponent
    savePanel.directoryURL = FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first!

    if let keyWindow = NSApp.keyWindow {
        savePanel.beginSheetModal(for: keyWindow, completionHandler: { result in
            responseHandler( result == .OK ? savePanel.url : nil )
         })
    }
    else
    {
        NSApp.activate(ignoringOtherApps: true)

        let result = savePanel.runModal()
        responseHandler( result == .OK ? savePanel.url : nil )
    }
}

并像这样调用 - 响应委托;用户单击其 UTI 已知的“数据”(二进制)文件上的下载链接,因此我们下载然后返回到较早的 URL:

    guard url.hasDataContent(), let suggestion = response.suggestedFilename else { decisionHandler(.allow); return }
    let downloadDir = FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first!
    let saveURL = downloadDir.appendingPathComponent(suggestion)
    saveURL.saveAs(responseHandler: { saveAsURL in
        if let saveAsURL = saveAsURL {
            self.loadFileAsync(url, to: saveAsURL, completion: { (path, error) in
                if let error = error {
                    NSApp.presentError(error)
                }
                else
                {
                    if appDelegate.isSandboxed() { _ = appDelegate.storeBookmark(url: saveAsURL, options: [.withSecurityScope]) }
                }
            })
        }

        decisionHandler(.cancel)
        self.backPress(self)
     })

我想我更喜欢旧的方式;-)

于 2020-03-17T21:13:53.737 回答
0

当您说.runModal您的代码做了一件非常非常奇怪的事情时:它停止并等待用户处理模态对话框(也称为阻塞)。这可以追溯到 OS X / Cocoa 的极早期,并且是一种异常行为。所以结果是,当我们到达方法和你的末尾时Swift.printreturn我们从模式对话框中返回,我们从中获得了价值。

但是,正如我所说,这完全是奇怪的。(事实上​​,我不确定我是否能想到任何其他类似的 Cocoa 调用。).beginSheetModal调用行为正常,即在调用之后您的代码继续进行并在模态表之前print以and结束有机会出现。模态表中发生的事情然后相对于此处的调用代码异步发生- 即稍后。因此,您不能从对话框中返回任何值,因为您需要一台时间机器来展望未来。这是这类事情的标准模式。return

于 2020-03-17T16:53:37.207 回答