我正在尝试提取用户在默认情况下选择的文档的URL"打开";我的基于文档的macOS应用程序的对话。我知道,fileWrapper被传递给init方法,但有没有一种方法可以从所述包装器中提取路径/URL?
谢谢,
Lars
DocumentGroup只需要绑定到文档来初始化ContentView,所以在文档上有一个函数来获取url&返回绑定:
应用程序:
import SwiftUI
@main
struct FileOpenApp: App {
var body: some Scene {
DocumentGroup(newDocument: FileOpenDocument()) { file in
ContentView(document: file.document.setSourceURL(file))
}
}
}
文件:
struct FileOpenDocument: FileDocument {
var sourceURL: URL?
init() {
}
// needs to be mutating to avoid "self is immutable" error
mutating func setSourceURL(_ config: FileDocumentConfiguration< FileOpenDocument >) -> Binding<FileOpenDocument> {
sourceURL = config.fileURL
return config.$document
}
}
如果有人单击"打开"(OK(按钮,打开面板会为您提供URL。NSOpenPanel
具有包含所选文件的URL的urls
属性。
如果打开成功,SwiftUI文件导入程序会为您提供一个URL。
.fileImporter(isPresented: $isImporting, allowedContentTypes:
[.png, .jpeg, .tiff], onCompletion: { result in
switch result {
case .success(let url):
// Use the URL to do something with the file.
case .failure(let error):
print(error.localizedDescription)
}
})
更新
SwiftUI的文档打开面板与文件导入器的工作方式不同。您可以尝试直接使用NSOpenPanel
。以下文章应该会有所帮助:
在基于SwiftUI的macOS应用程序中保存和打开面板
FileWrapper
有一个filename
字段,所以您可能会使用它。
非居民外国人接受的答案可以简化,DocumentGroup闭包需要绑定到文档来初始化ContentView,因此在文档上声明一个函数来获取源URL&返回配置,然后该配置可以提供文档绑定:
struct FileOpenDocument: FileDocument {
var sourceURL: URL?
mutating func setSourceURL(config: FileDocumentConfiguration<FileOpenDocument>) -> FileDocumentConfiguration<FileOpenDocument> {
sourceURL = config.fileURL
return config
}
}
DocumentGroup初始值设定项随后变为:
@main
struct FileOpenApp: App {
var body: some Scene {
DocumentGroup(newDocument: FileOpenDocument()) { file in
ContentView(document: file.document.setSourceURL(file).$document)
}
}
}
无需修改ContentView。
不能将FileDocument声明为具有可变方法的结构。这样做将触发可怕的从视图内发布更改。不允许更新,这将导致未定义的行为问题。在Apples解决这个问题之前,我们应该坚持将FileDocument声明为类,而不是Struct。这是为了规避问题,而不是解决问题,因为大多数时候都需要使用structs。
我的解决方案是将我的文件文档声明为类。这是我正在做的一个实验:
class MyDocument: FileDocument {
var pdfURL: URL?
var pdfFile: PDFDocument?
init(pdfDocument: PDFDocument = PDFDocument()) {
pdfFile = pdfDocument
}
static var readableContentTypes: [UTType] { [.pdf] }
required init(configuration: ReadConfiguration) throws {
guard let data = configuration.file.regularFileContents
else {
throw CocoaError(.fileReadCorruptFile)
}
pdfFile = PDFDocument(data: data)
}
func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
return .init()
}
func setSourceURL(config: FileDocumentConfiguration<GPTFileDialogDocument>) -> FileDocumentConfiguration<GPTFileDialogDocument> {
pdfURL = config.fileURL
return config
}
}
通过这种方式,您可以保留与@dang建议的相同的DocumentGroup初始值设定项:
@main
struct FileOpenApp: App {
var body: some Scene {
DocumentGroup(newDocument: FileOpenDocument()) { file in
ContentView(document: file.document.setSourceURL(file).$document)
}
}
}