title: How to popup a document picker in ios and macos using catalyst
body: <p>I'm trying to popup a document picker using mac catalyst, but all I get is a blank screen.</p>
  
  <p>All works well on ios 13.2.2 on iPad and iPhone, but not on macos 10.15.1 catalina.</p>
  
  <p>Does anyone knows how to popup a document picker in both ios and macos using catalyst?</p>
  
  <p>with my entitlements file having:</p>
  
  <pre><code>&lt;key&gt;com.apple.security.app-sandbox&lt;/key&gt;
  &lt;false/&gt;
  </code></pre>
  
  <p>Here is the test code that shows the problem.</p>
  
  <pre><code>import Foundation
  import SwiftUI
  
  struct ContentView: View {
  @State var isFilePickerShown = false
  
  var body: some View {
      VStack {
          Button(action: { self.isFilePickerShown.toggle() }) {
              Image(systemName: "rectangle.and.paperclip").resizable().frame(width: 70, height: 70)
          }
      }.sheet(isPresented: $isFilePickerShown, onDismiss: {self.isFilePickerShown = false}) {
          DocPickerViewController(callback: self.filePicked, onDismiss: { self.isFilePickerShown = false })
      }
  }
  
  func filePicked(_ url: URL) {
      print("\nThe url is: \(url)")
  }
  
  }
  
  struct DocPickerViewController: UIViewControllerRepresentable {
  
  private let docTypes: [String] = ["com.adobe.pdf", "public.text", "public.composite-content"]
  var callback: (URL) -&gt; ()
  private let onDismiss: () -&gt; Void
  
  init(callback: @escaping (URL) -&gt; (), onDismiss: @escaping () -&gt; Void) {
      self.callback = callback
      self.onDismiss = onDismiss
  }
  
  func makeCoordinator() -&gt; Coordinator { Coordinator(self) }
  
  func updateUIViewController(_ uiViewController: UIDocumentPickerViewController, context: UIViewControllerRepresentableContext&lt;DocPickerViewController&gt;) {
  }
  
  func makeUIViewController(context: Context) -&gt; UIDocumentPickerViewController {
      let controller = UIDocumentPickerViewController(documentTypes: docTypes, in: .import)
      controller.allowsMultipleSelection = false
      controller.delegate = context.coordinator
      return controller
  }
  
  class Coordinator: NSObject, UIDocumentPickerDelegate {
      var parent: DocPickerViewController
      init(_ pickerController: DocPickerViewController) {
          self.parent = pickerController
      }
      func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
          parent.callback(urls[0])
          parent.onDismiss()
      }
      func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
          parent.onDismiss()
      }
  }
  }
  </code></pre>
  
  <p>I got something going with the following code. But really this is
  a messy business and I feel this is not the answer. </p>
  
  <p>Now I have the same problem trying to display
  a UIActivityViewController. I can display it on Mac using the same approach but 
  I can't control where it shows up. It's always at (0,0).</p>
  
  <pre><code>struct FilePicker: UIViewControllerRepresentable {
  
  private let docTypes: [String] = ["com.adobe.pdf", "public.text", "public.composite-content"]
  private let controller: FilePickerController?
  
  var callback: (URL) -&gt; ()
  
  private let onDismiss: () -&gt; Void
  
  init(callback: @escaping (URL) -&gt; (), onDismiss: @escaping () -&gt; Void) {
      self.callback = callback
      self.onDismiss = onDismiss
      self.controller = FilePickerController(documentTypes: docTypes, mode: .import)
  }
  
  func makeCoordinator() -&gt; Coordinator {
      return Coordinator(self)
  }
  
  func updateUIViewController(_ uiViewController: FilePickerController, context: UIViewControllerRepresentableContext&lt;FilePicker&gt;) { }
  
  func makeUIViewController(context: Context) -&gt; FilePickerController {
      return controller!
  }
  
  class Coordinator: NSObject, FilePickerControllerDelegate {
      var parent: FilePicker
  
      init(_ filePicker: FilePicker) {
          self.parent = filePicker
          super.init()
          self.parent.controller?.delegate = self
      }
  
      func documentPicker(_ controller: FilePickerController, didPickDocumentsAt urls: [URL]) {
          parent.callback(urls[0])
          parent.onDismiss()
      }
  
      func documentPickerWasCancelled(_ controller: FilePickerController) {
          parent.onDismiss()
      }
  }
  }
  
  
  protocol FilePickerControllerDelegate: class {
  func documentPickerWasCancelled(_ controller: FilePickerController)
  func documentPicker(_ controller: FilePickerController, 
  didPickDocumentsAt urls: [URL])
  }
  
  class FilePickerController: UIViewController, UIDocumentPickerDelegate {
  
  weak var delegate: FilePickerControllerDelegate?
  
  let viewController: UIDocumentPickerViewController?
  
  public init(documentTypes: [String], mode: UIDocumentPickerMode) {
      viewController = UIDocumentPickerViewController(documentTypes: documentTypes, in: mode)
      super.init(nibName: nil, bundle: nil)
  }
  
  required public init?(coder: NSCoder) {
      viewController = UIDocumentPickerViewController(coder: coder)
      super.init(coder: coder)
  }
  
  override func viewWillAppear(_ animated: Bool) {
      super.viewWillAppear(animated)
      if let viewController = viewController {
          viewController.delegate = self
          self.present(viewController, animated: animated)
      }
  }
  
  func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
      self.dismiss(animated: false) {
          self.delegate?.documentPicker(self, didPickDocumentsAt: urls)
      }
  }
  
  func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
      self.dismiss(animated: false) {
          self.delegate?.documentPickerWasCancelled(self)
      }
  }
  
  }
  </code></pre>
  
  <p>I call it like this:</p>
  
  <pre><code>.sheet(isPresented: $isShown, onDismiss: {self.isShown = false}) {
          #if targetEnvironment(macCatalyst)
              FilePicker(callback: self.filePicked, onDismiss: { self.isShown = false })
          #else
              DocPickerViewController(callback: self.filePicked, onDismiss: { self.isShown = false })
          #endif
      }
  </code></pre>