title: UIImagePickerController what is the right approach to avoid error Code=13 "query cancelled"
body: <p>I'm implementing a photopicker in my project and it works or not, with the same code, depending the way I implement it. In my first approach I was using a custom UIAlertAction class and doing all the stuff in there, to have my main controller lighter, but the picker delegate was never called, instead it prints an error message in the console (<strong>[discovery] errors encountered while discovering extensions: Error Domain=PlugInKit Code=13 "query cancelled" UserInfo={NSLocalizedDescription=query cancelled}</strong>) and I would like to discuss if the way I were implementing the picker was right or wrong and why? Or if it's a bug from apple. I've been googling for a while and checking all the related questions in stack overflow, and anything has worked for me except to put the picker code in my main controller. </p>
  
  <p>Here is the code of my main controller, when it was not calling the delegate:</p>
  
  <p><strong>First approach that give me error and don't call delegates</strong></p>
  
  <pre><code>    import UIKit
      import MobileCoreServices
      import Photos
      class ViewController: UIViewController {
  
          @IBOutlet weak var lblMain: UILabel!
          @IBOutlet weak var buttonsBottom: NSLayoutConstraint!
  
          @IBOutlet weak var imgFromUser: UIImageView!
  
  
          override func viewDidLoad() {
              super.viewDidLoad()
              // Do any additional setup after loading the view, typically from a nib.
              hideButtons()
          }
          override func viewDidAppear(_ animated: Bool) {
              showButtons()
              checkPermission()
          }
          func checkPermission() {
              let photoAuthorizationStatus = PHPhotoLibrary.authorizationStatus()
              switch photoAuthorizationStatus {
              case .authorized: print("Access is granted by user")
              case .notDetermined: PHPhotoLibrary.requestAuthorization({
                  (newStatus) in
                  print("status is \(newStatus)")
                  if newStatus == PHAuthorizationStatus.authorized { print("success") }
              })
              case .restricted: print("User do not have access to photo album.")
              case .denied: print("User has denied the permission.")
              }
          }
  
  
          override func didReceiveMemoryWarning() {
              super.didReceiveMemoryWarning()
              // Dispose of any resources that can be recreated.
          }
  
          func hideButtons()
          {
              buttonsBottom.constant += self.view.frame.size.height * 0.15
          }
  
          func showButtons(){
              UIView.animate(withDuration: 0.5) {
  
              }
              UIView.animate(withDuration: 0.5, animations: {
                  self.buttonsBottom.constant = 0
                  self.view.layoutIfNeeded()
              }) { (completed) in
                  self.lblMain.text = firstController.lblMain
              }
  
          }
          @IBAction func addImagePressed(_ sender: Any) {
              let alertViewController : AlertAction = AlertAction.init(controller: self, type: .photoGallery)
  
              self.present((alertViewController.setType(alert: .photoGallery)), animated: true, completion: nil)
          }
  }
  </code></pre>
  
  <p>And this is my custom AlertAction class, it implements the picker &amp; navigation delegate, creates the UIImagePickerController, sets the delegate to it, creates the alert action and set it to present the main view controller, adds it to a UIAlertController and gets returned to the main view controller which present it:</p>
  
  <pre><code>import UIKit
  import Photos
  class AlertAction: UIAlertAction {
  
      var destinationController : ViewController?
      var imagePicker = UIImagePickerController()
  
      convenience init(controller : ViewController, type : type) {
          self.init()
          destinationController = controller
  
          //Init picker
          imagePicker.delegate = self
          imagePicker.sourceType = type == .photoGallery ? UIImagePickerControllerSourceType.photoLibrary : UIImagePickerControllerSourceType.camera
          imagePicker.allowsEditing = false
      }
  
      enum type {
          case camera
          case photoGallery
      }
      var alertType : type = .camera
  
      func setType(alert : type) -&gt; UIAlertController {
          alertType = alert
          return alertType == .camera ? newAlert() : newAlert()
      }
  
      func newAlert() -&gt; UIAlertController{
  
          //set alert text
          let alertText = alertType == .camera ? AlertText.typeCamera : AlertText.typeGalery
  
          let myAlert = UIAlertController(title: AlertText.title, message: "", preferredStyle: .actionSheet)
  
          if alertType == .camera {
              myAlert.addAction(getCameraAction(alertText: alertText))
              return myAlert
          }
          else{
              myAlert.addAction(getGalleryAction(alertText: alertText))
              return myAlert
          }
      }
  
      func getCameraAction(alertText : String) -&gt; UIAlertAction{
  
          let cameraAction = UIAlertAction(title : alertText, style : .default) { (action) in
              if UIImagePickerController.isSourceTypeAvailable(.camera) {
                  self.destinationController!.present(self.imagePicker, animated: true, completion: nil)
              }
          }
          return cameraAction
      }
  
      func getGalleryAction(alertText : String) -&gt; UIAlertAction{
          let photoLibraryAction = UIAlertAction(title: alertText, style: .default) { (action) in
              if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
                  self.destinationController!.present(self.imagePicker, animated: true, completion: nil)
              }
          }
          return photoLibraryAction
      }
  }
  
  extension AlertAction : UIImagePickerControllerDelegate {
      @objc func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
          let mediaType = info[UIImagePickerControllerMediaType] as! NSString
          if mediaType.isEqual(to: kCIAttributeTypeImage as String){
              destinationController!.imgFromUser.image = info[UIImagePickerControllerOriginalImage] as? UIImage
          }
          destinationController!.dismiss(animated: true, completion: nil)
      }
  
      @objc func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
          destinationController!.dismiss(animated: true, completion: nil)
      }
  }
  
  extension AlertAction : UINavigationControllerDelegate {
  
  }
  </code></pre>
  
  <p>After reading a while, I've been trying all the posible solutions in this custom class but nothing worked. 
  Then I tried to implement a picker creation method in my main view controller and it worked. 
  So my question is very simple, why the delegate methods get called only if I do all the coding stuff in the main view controller but don't work in a custom class?</p>
  
  <p>Here is the code that I'm currently using and works:</p>
  
  <p><strong>Second approach that works, all the code in the same ViewController</strong></p>
  
  <pre><code>import UIKit
  import MobileCoreServices
  import Photos
  class ViewController: UIViewController {
  
      @IBOutlet weak var lblMain: UILabel!
      @IBOutlet weak var buttonsBottom: NSLayoutConstraint!
  
      @IBOutlet weak var imgFromUser: UIImageView!
  
  
      override func viewDidLoad() {
          super.viewDidLoad()
          // Do any additional setup after loading the view, typically from a nib.
          hideButtons()
      }
      override func viewDidAppear(_ animated: Bool) {
          showButtons()
          checkPermission()
      }
      func checkPermission() {
          let photoAuthorizationStatus = PHPhotoLibrary.authorizationStatus()
          switch photoAuthorizationStatus {
          case .authorized: print("Access is granted by user")
          case .notDetermined: PHPhotoLibrary.requestAuthorization({
              (newStatus) in
              print("status is \(newStatus)")
              if newStatus == PHAuthorizationStatus.authorized { print("success") }
          })
          case .restricted: print("User do not have access to photo album.")
          case .denied: print("User has denied the permission.")
          }
      }
  
  
      override func didReceiveMemoryWarning() {
          super.didReceiveMemoryWarning()
          // Dispose of any resources that can be recreated.
      }
  
      func hideButtons()
      {
          buttonsBottom.constant += self.view.frame.size.height * 0.15
      }
  
      func showButtons(){
          UIView.animate(withDuration: 0.5) {
  
          }
          UIView.animate(withDuration: 0.5, animations: {
              self.buttonsBottom.constant = 0
              self.view.layoutIfNeeded()
          }) { (completed) in
              self.lblMain.text = firstController.lblMain
          }
  
      }
      @IBAction func addImagePressed(_ sender: Any) {
          self.present(addPicker(), animated: true, completion: nil)
      }
  
      //MARK: Picker methods
      func addPicker()-&gt;UIAlertController{
          let alertText = AlertText.typeGalery
          let myAlert = UIAlertController(title: AlertText.title, message: "", preferredStyle: .actionSheet)
          let cameraAction = UIAlertAction(title : alertText, style : .default) { (action) in
              if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
                  let imagePicker = UIImagePickerController()
                  imagePicker.delegate = self
                  imagePicker.sourceType = .photoLibrary
                  imagePicker.allowsEditing = true
                  self.present(imagePicker, animated: true, completion: nil)
              }
          }
          myAlert.addAction(cameraAction)
          return myAlert
      }
  }
  
  extension ViewController : UIImagePickerControllerDelegate {
      @objc func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
          let mediaType = info[UIImagePickerControllerMediaType] as! NSString
          if let image = info[UIImagePickerControllerOriginalImage] as? UIImage{
              self.imgFromUser.image = image
          }
          if mediaType.isEqual(to: kCIAttributeTypeImage as String){
              self.imgFromUser.image = info[UIImagePickerControllerOriginalImage] as? UIImage
          }
          self.dismiss(animated: true, completion: nil)
      }
  
      @objc func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
          self.dismiss(animated: true, completion: nil)
      }
  }
  
  extension ViewController : UINavigationControllerDelegate {
  
  }
  </code></pre>
  
  <p>Update: the error <strong>[discovery] errors encountered while discovering extensions: Error Domain=PlugInKit Code=13 "query cancelled" UserInfo={NSLocalizedDescription=query cancelled}</strong> still appears in my second implementation, but only when I remove @objc before the picker delegate method and environement varibable OS_ACTIVITY_MODE = disable is not set, but the code still works anda the delegates are called correctly (in the second implementation) so basically this error is not related with the code functionality and don't describe anything useful</p>