How to use UIDocumentPickerViewController inside a ContainerView?

153 views Asked by At

I am displaying a UIDocumentPickerViewController inside a containerView so user can pick document while being able to interact with other controls on the screen. It works and the documentPickerWasCancelled delegate does kick in when user taps cancel button. But when user selects a file and taps Open, the didPickDocumentsAt delegate method does not fire.

If I present the picker using present(pickerViewController, animated: true, completion: nil) then didPickDocumentsAt fires fine.

How can I make it work inside a Container?

class MainVC: UIViewController, UIDocumentPickerDelegate {
...
override func viewDidAppear(_ animated: Bool) {
    let pickerViewController = UIDocumentPickerViewController(forOpeningContentTypes: [.item], asCopy: true)
    pickerViewController.delegate = self
    self.addChild(pickerViewController)
    self.containerView.addSubview(pickerViewController.view)
    pickerViewController.view.frame = self.containerView.bounds
    pickerViewController.didMove(toParent: self)
}
func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
        print("cancelled") // <- Works
    }
    
    func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
        print("picked") // <- Does not work when inside ContainerView
...
}
1

There are 1 answers

4
iUrii On BEST ANSWER

You can fix this by subclassing UIDocumentPickerViewController and overriding an internal _callDelegateWithSelectedURLsAndDismiss: method which works when the controller is presented modally only.

class DocumentPickerViewController: UIDocumentPickerViewController {
  @objc
  func _callDelegateWithSelectedURLsAndDismiss(_ urls: [URL]) {
    delegate?.documentPicker?(self, didPickDocumentsAt: urls)
  }
}

Now the following code works for picking files:

class ViewController: UIViewController {
  @IBOutlet private var containerView: UIView!
  
  override func viewDidAppear(_ animated: Bool) {
    let pickerViewController = DocumentPickerViewController(forOpeningContentTypes: [.item], asCopy: true)
    pickerViewController.delegate = self
    self.addChild(pickerViewController)
    self.containerView.addSubview(pickerViewController.view)
    pickerViewController.view.frame = self.containerView.bounds
  }
}

extension ViewController: UIDocumentPickerDelegate {
  func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
    print(#function) // <- Works
  }
  
  func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
    print(#function) // <- Works
  }
}