Search code examples
iosswiftswift3uiimagepickercontroller

didFinishPickingImage does not get triggered


I have a class

class ActivitiesMainPageController: UICollectionViewController      ,UIImagePickerControllerDelegate, UINavigationControllerDelegate{

 override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

    switch indexPath.item {

    case 0 :
        let takePictureInstance = takePictures()
        takePictureInstance.presentCamera()
    }

}

The takePictures() is s custom class

class takePictures: UIViewController, UIImagePickerControllerDelegate, UIAlertViewDelegate, UINavigationControllerDelegate
{
   var imagePicker: UIImagePickerController! = UIImagePickerController()
  func presentCamera()
    {

    if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera)
    {

        let objViewController =  UIApplication.shared.keyWindow?.rootViewController

        imagePicker =  UIImagePickerController()
        imagePicker.delegate = self
        imagePicker.allowsEditing = false
        imagePicker.sourceType = UIImagePickerControllerSourceType.camera
        objViewController?.present(imagePicker,animated: true,completion: nil)
   }
    else
    {
        // error msg
        print ("error displaying Camera")
         noCamera()
    }
}



  func imagePickerController(_ picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {

    print(self.Tag + "image picker controller")

    self.dismiss(animated: true, completion: nil)
  }
}

The didfinishpickingimage never gets triggered. I don't see the print statement. After reading the SO here, I think I am not doing the delegate correctly. Can you please help?


Solution

  • The problem is in your ActivitiesMainPageController class. It's a memory management issue. You create a local instance of your takePictures class (FYI - class names should start with uppercase letters), and then call the presentCamera method. And then the takePictureInstance variable immediately goes out of scope. This means it has no more references and it gets deallocated.

    So at this point, the image picker's (weak) delegate becomes nil. This is why the image picker delegate method is never called.

    There are two ways to fix this:

    1. Keep a strong reference to the takePictures instance inside your ActivitiesMainPageController class (use a property instead of a local variable). But this has the problem of not knowing when to release the instance.
    2. Perform a little trick inside the takePictures class where it keeps a strong reference to itself when created, and then releases that strong reference after the image picker is dismissed.

    Option 2 can be implemented like this:

    class takePictures: UIViewController, UIImagePickerControllerDelegate, UIAlertViewDelegate, UINavigationControllerDelegate
    {
        var strongSelf: takePictures?
        var imagePicker: UIImagePickerController! = UIImagePickerController()
    
        func presentCamera()
        {
            if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera)
            {
                let objViewController =  UIApplication.shared.keyWindow?.rootViewController
    
                imagePicker =  UIImagePickerController()
                imagePicker.delegate = self
                imagePicker.allowsEditing = false
                imagePicker.sourceType = UIImagePickerControllerSourceType.camera
                objViewController?.present(imagePicker,animated: true,completion: nil)
                strongSelf = self // keep me around
            }
            else
            {
                // error msg
                print ("error displaying Camera")
                noCamera()
            }
        }
    
        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {
            print(self.Tag + "image picker controller")
    
            self.dismiss(animated: true, completion: nil)
            strongSelf = nil // let me go
        }
    }