从标准 Swift 基于文档的应用程序的打开对话框中获取 URL
Get URL from Open dialog of standard Swift document-based application
我正在尝试提取用户在我基于文档的 macOS 应用程序的默认“打开”对话框中选择的文档的 URL。我知道,一个 fileWrapper 被传递给了 init 方法,但是有没有办法从所述包装器中提取 path/URL?
谢谢,
拉斯
FileWrapper
有一个 filename
字段,因此您可能会使用它。
如果有人单击打开(确定)按钮,打开的面板会为您提供 URL。 NSOpenPanel
有一个 urls
属性,其中包含所选文件的 URL。
如果打开成功,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
。以下文章应该有所帮助:
我能让它工作的唯一方法是向内容视图添加自定义初始化程序,将 URL 写回文档。非常不优雅,但我们在这里:
应用程序:
import SwiftUI
@main
struct FileOpenApp: App {
var body: some Scene {
DocumentGroup(newDocument: FileOpenDocument()) { file in
ContentView(document: file.$document, fileURL: file.fileURL)
}
}
}
文件:
struct FileOpenDocument: FileDocument {
var text: String
var originalFilePath: String
var firstOpen: Bool
init(text: String = "Hello, world!") {
self.text = text
self.firstOpen = true
self.originalFilePath = "NewFile Path"
}
static var readableContentTypes: [UTType] { [.exampleText, .CSVtext, .plainText] }
init(configuration: ReadConfiguration) throws {
guard let data = configuration.file.regularFileContents,
let string = String(data: data, encoding: .utf8)
else {
throw CocoaError(.fileReadCorruptFile)
}
text = string
self.firstOpen = true
self.originalFilePath = "ReadPath"
}
func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
let data = text.data(using: .utf8)!
return .init(regularFileWithContents: data)
}
}
内容视图:
struct ContentView: View {
@Binding var document: FileOpenDocument
var documentURL: URL?
init(document: Binding<FileOpenDocument>, fileURL: URL?){
self._document = document
self.documentURL = fileURL
if document.firstOpen.wrappedValue == true {
if let path = self.documentURL?.path {
self.document.originalFilePath = path
document.firstOpen.wrappedValue = false
}
}
}
var body: some View {
TextEditor(text: $document.text)
Text("ContentView Path: \(self.documentURL?.path ?? "no Document Path")")
Text("Document Path: " + document.originalFilePath)
}
}
我正在尝试提取用户在我基于文档的 macOS 应用程序的默认“打开”对话框中选择的文档的 URL。我知道,一个 fileWrapper 被传递给了 init 方法,但是有没有办法从所述包装器中提取 path/URL?
谢谢,
拉斯
FileWrapper
有一个 filename
字段,因此您可能会使用它。
如果有人单击打开(确定)按钮,打开的面板会为您提供 URL。 NSOpenPanel
有一个 urls
属性,其中包含所选文件的 URL。
如果打开成功,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
。以下文章应该有所帮助:
我能让它工作的唯一方法是向内容视图添加自定义初始化程序,将 URL 写回文档。非常不优雅,但我们在这里:
应用程序:
import SwiftUI
@main
struct FileOpenApp: App {
var body: some Scene {
DocumentGroup(newDocument: FileOpenDocument()) { file in
ContentView(document: file.$document, fileURL: file.fileURL)
}
}
}
文件:
struct FileOpenDocument: FileDocument {
var text: String
var originalFilePath: String
var firstOpen: Bool
init(text: String = "Hello, world!") {
self.text = text
self.firstOpen = true
self.originalFilePath = "NewFile Path"
}
static var readableContentTypes: [UTType] { [.exampleText, .CSVtext, .plainText] }
init(configuration: ReadConfiguration) throws {
guard let data = configuration.file.regularFileContents,
let string = String(data: data, encoding: .utf8)
else {
throw CocoaError(.fileReadCorruptFile)
}
text = string
self.firstOpen = true
self.originalFilePath = "ReadPath"
}
func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
let data = text.data(using: .utf8)!
return .init(regularFileWithContents: data)
}
}
内容视图:
struct ContentView: View {
@Binding var document: FileOpenDocument
var documentURL: URL?
init(document: Binding<FileOpenDocument>, fileURL: URL?){
self._document = document
self.documentURL = fileURL
if document.firstOpen.wrappedValue == true {
if let path = self.documentURL?.path {
self.document.originalFilePath = path
document.firstOpen.wrappedValue = false
}
}
}
var body: some View {
TextEditor(text: $document.text)
Text("ContentView Path: \(self.documentURL?.path ?? "no Document Path")")
Text("Document Path: " + document.originalFilePath)
}
}