如何在“ UIKit for Mac”平台上使用SwiftUI打开文件对话框?

时间:2019-06-18 09:23:21

标签: swift macos swiftui uikitformac

NSOpenPanel在“ UIKit for Mac”平台上不可用: https://developer.apple.com/documentation/appkit/nsopenpanel

如果Apple不提供内置方式,我想有人会基于SwiftUI和FileManager创建一个显示选择文件对话框的库。

3 个答案:

答案 0 :(得分:11)

这是使用Catalyst和UIKit为macOS选择文件的解决方案

在您的swiftUI视图中:

Button("Choose file") {
    let picker = DocumentPickerViewController(
        supportedTypes: ["log"], 
        onPick: { url in
            print("url : \(url)")
        }, 
        onDismiss: {
            print("dismiss")
        }
    )
    UIApplication.shared.windows.first?.rootViewController?.present(picker, animated: true)
}

DocumentPickerViewController类:

class DocumentPickerViewController: UIDocumentPickerViewController {
    private let onDismiss: () -> Void
    private let onPick: (URL) -> ()

    init(supportedTypes: [String], onPick: @escaping (URL) -> Void, onDismiss: @escaping () -> Void) {
        self.onDismiss = onDismiss
        self.onPick = onPick

        super.init(documentTypes: supportedTypes, in: .open)

        allowsMultipleSelection = false
        delegate = self
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

extension DocumentPickerViewController: UIDocumentPickerDelegate {
    func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
        onPick(urls.first!)
    }

    func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
        onDismiss()
    }
}

答案 1 :(得分:4)

UIDocumentPickerViewControllerUIDocumentBrowserViewController都在Catalyst中工作。完全像在iOS上一样使用它们,它们将“神奇地”显示为标准Mac打开/保存对话框。

如果需要,这里是一个很好的示例:https://appventure.me/guides/catalyst/how/open_save_export_import.html

答案 2 :(得分:1)

它可能不是现成的SwiftUI组件,但您可以按以下方式使用它:

struct ContentView : View {

    @State var selectedURL: URL?

    var body: some View {
        VStack {
            if selectedURL != nil {
                Text("Selected: \(selectedURL!.absoluteString)")
            } else {
                Text("No selection")
            }
            Button(action: {
                let panel = NSOpenPanel()
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
                    let result = panel.runModal()
                    if result == .OK {
                        self.selectedURL = panel.url
                    }
                }
            }) {
                Text("Select file")
            }
        }
        .frame(width: 640, height: 480)
    }

}