'Can't select a folder with UIViewRepresentable & UIDocumentPicker
I'm trying to create a picker for a user to choose a folder in a SwiftUI app. However, there doesn't seem to be any SwiftUI document picker yet so I was attempting to use UIViewRepresentable
to display a document picker using the folder document picker outlined here: https://developer.apple.com/documentation/uikit/view_controllers/providing_access_to_directories. However, as seen in the image below I'm not actually able to select the folder in any way - am I missing specific to use the picker with SwiftUI?
FolderPicker
code:
struct FolderPicker: UIViewControllerRepresentable {
@Binding var folderURL: String?
func makeCoordinator() -> Coordinator {
return FolderPicker.Coordinator(parent: self)
}
func makeUIViewController(context: UIViewControllerRepresentableContext<FolderPicker>) -> UIDocumentPickerViewController {
let picker = UIDocumentPickerViewController(documentTypes: ["kUTTypeFolder"], in: .import)
picker.delegate = context.coordinator
return picker
}
func updateUIViewController(_ uiViewController: UIDocumentPickerViewController, context: UIViewControllerRepresentableContext<FolderPicker>) {}
class Coordinator: NSObject, UIDocumentPickerDelegate {
var parent: FolderPicker
init(parent: FolderPicker) {
self.parent = parent
}
internal func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL){
print(url)
parent.folderURL = url.absoluteString
}
}
}
which is in a TestView
:
struct TestView: View {
@State var displayPicker = false
var body: some View {
Button(action: {displayPicker.toggle}, label: "toggle")
.sheet(isPresented: $showPicker) {
FolderPicker(folderURL: $url)
}
}
}
Solution 1:[1]
kUTTypeFolder is not a string.
The correct way is
let picker = UIDocumentPickerViewController(documentTypes: [kUTTypeFolder as String], in: .import)
The constant kUTTypeFolder
comes from import CoreServices
.
Also, public init(documentTypes allowedUTIs: [String], in mode: UIDocumentPickerMode)
and optional func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL)
is deprecated
So use, public convenience init(forOpeningContentTypes contentTypes: [UTType])
and optional func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL])
Final code is :
struct FolderPicker: UIViewControllerRepresentable {
@Binding var folderURL: String?
func makeCoordinator() -> Coordinator {
return FolderPicker.Coordinator(parent: self)
}
func makeUIViewController(context: UIViewControllerRepresentableContext<FolderPicker>) -> UIDocumentPickerViewController {
let picker = UIDocumentPickerViewController(forOpeningContentTypes: [.folder])
picker.delegate = context.coordinator
return picker
}
func updateUIViewController(_ uiViewController: UIDocumentPickerViewController, context: UIViewControllerRepresentableContext<FolderPicker>) {}
class Coordinator: NSObject, UIDocumentPickerDelegate {
var parent: FolderPicker
init(parent: FolderPicker) {
self.parent = parent
}
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
guard let url = urls.first else {
return
}
print(url)
parent.folderURL = url.absoluteString
}
}
}
Solution 2:[2]
Use .fileImporter presentation modifire (above ios 14)
.fileImporter(isPresented: $showDocumentPicker,
allowedContentTypes: [.folder],
allowsMultipleSelection: true)
{ result in
// processing results Result<[URL], Error>
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 |