15

So I've been meddling with "moving" a small SwiftUI iPad app to the Mac, and I've hit a bit of a speed bump with UIDocumentPickerViewController. I have wrapped the UIDocumentPickerViewController in a UIViewControllerRepresentable like so :

struct DocumentPickerView: UIViewControllerRepresentable {
  func makeUIViewController(context: Context) -> UIDocumentPickerViewController {
    let documentPicker = UIDocumentPickerViewController(documentTypes: [(kUTTypeImage as String)], in: .import)
    return documentPicker
  }

  func updateUIViewController(_ uiViewController: UIDocumentPickerViewController, context: Context) {

  }
}

And displaying it like this:

struct ContentView: View {
@State var shows = false
var body: some View {
    Button(action: { self.shows.toggle() }) {
        Text("Select File")
    }
    .sheet(isPresented: self.$shows) {
        DocumentPickerView()
    }
  }
}

On the iPad all is working well, iPad

But when on on the Mac, the UIDocumentPickerViewControllerdoesnt show and we get this blank modal:

Mac

11
  • 3
    Well if I use UIKit with Catalyst, it opens a macos file picker. When using SwiftUI, with catalyst, i get the blank view. I would expect the same behaviour for SwiftUI. Commented Nov 30, 2019 at 13:29
  • I could not reproduce your issue. It shows as you are expecting here. I run into another issue selecting a file though. It does nothing and log error: Failed to create an FPSandboxingURLWrapper for file ... Error: Error Domain=NSPOSIXErrorDomain Code=1 "couldn't issue sandbox extension com.apple.app-sandbox.read-write for '/..fileName': Operation not permitted" UserInfo={NSDescription=couldn't issue sandbox extension com.apple.app-sandbox.read-write for '/../fileName.png': Operation not permitted}. Using UIDocumentBrowserViewControllerinstead fixes my issue. Commented Dec 2, 2019 at 12:17
  • I'm having the same problem. This has to be a bug in SwiftUI. It should really transform the UIDocumentPickerViewController into an NSOpenPanel on macOS. Bug for sure! Commented Dec 5, 2019 at 14:25
  • 1
    If you are working with a Document-based app as I'm doing you can work around the problem by letting the UIDocumentBrowserViewController present the dialog. It's a pain... but at least it works ;-) Commented Dec 5, 2019 at 14:48
  • 1
    let controller = UIDocumentPickerViewController(url: tempURL, in: .moveToService) controller.delegate = self if let presentedViewController = self.presentedViewController { // let the ContentView present the self.modalSelection = .save presentedViewController.present(controller, animated: true) } Commented Dec 5, 2019 at 14:49

2 Answers 2

1

I replaced deprecated method and enabled asked entitlement for provided topic starter code and it works.

Tested with Xcode 13.3 / macOS 12.2

import UniformTypeIdentifiers
struct DocumentPickerView: UIViewControllerRepresentable {
  func makeUIViewController(context: Context) -> UIDocumentPickerViewController {
    let documentPicker = UIDocumentPickerViewController(forOpeningContentTypes: [UTType.image], asCopy: true)
    return documentPicker
  }

  func updateUIViewController(_ uiViewController: UIDocumentPickerViewController, context: Context) {

  }
}

config

and demo opening standard macOS picker

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

0

For some reason (I'm not aware of further specific details), the following worked for me (for Catalyst):

Instead of using in: .import

let documentPicker = UIDocumentPickerViewController(
    documentTypes: [(kUTTypeImage as String)], 
    in: .import
)

Use in: .open

let documentPicker = UIDocumentPickerViewController(
    documentTypes: [(kUTTypeImage as String)], 
    in: .open
)

I haven't checked if the functionality is maintained in iOS, but perhaps you can use some sort of "flag" to determine wether to use .import or .open

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.