I am trying to extract the URL of the document a user has selected in the default "Open" dialogue of my document based macOS application. I understand, a fileWrapper is passed to the init method but is there a way of extracting the path/URL from said wrapper?
Thanks,
Lars
The open panel gives you the URL if someone clicks the Open (OK) button. NSOpenPanel has a urls property that contains the URLs of the selected files.
SwiftUI file importers give you a URL if the open was successful.
.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)
}
})
UPDATE
SwiftUI's document opening panel works differently than the file importer. You could try working with NSOpenPanel directly. The folllowing article should help:
The only way I could get this to work was to add a custom initializer to the content view that writes the URL back to the document. Very inelegant, yet here we are:
App:
import SwiftUI
@main
struct FileOpenApp: App {
var body: some Scene {
DocumentGroup(newDocument: FileOpenDocument()) { file in
ContentView(document: file.$document, fileURL: file.fileURL)
}
}
}
Document:
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)
}
}
ContentView:
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)
}
}