1

I have a class where I am calling the UIImagePickerController to select an image and return it so I can use it somewhere else in my code.

Now I set the delegate and implement the necessary function I need, but the delegate functions aren't being called.

The portion of my code that has the issue:

import UIKit

typealias PhotoTakingHelperCallback = (UIImage? -> Void)

class PhotoTakingHelper: NSObject
{

    weak var viewController:UIViewController!
    var callback: PhotoTakingHelperCallback
    var imagePickerController: UIImagePickerController?

    init(viewController:UIViewController , callback:PhotoTakingHelperCallback) {

        self.viewController = viewController

        self.callback = callback
        super.init()
        showPhotoSourceSelection()
    }


    func showPhotoSourceSelection() {
        let alertController = UIAlertController(title: nil, message: "Where do you want to get your picture from?", preferredStyle: .ActionSheet)

        let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)

        alertController.addAction(cancelAction)

        let photoLibraryAction = UIAlertAction(title: "Photo from Library", style: .Default) { (action) -> Void in
            self.showImagePickerController(.PhotoLibrary)
        }

        alertController.addAction(photoLibraryAction)

        if (UIImagePickerController.isCameraDeviceAvailable(.Rear) ) {
            let cameraAction = UIAlertAction(title: "Photo from Camera", style: .Default, handler: { (action) -> Void in
                self.showImagePickerController(.Camera)
            })

            alertController.addAction(cameraAction)
        }

        viewController.presentViewController(alertController, animated: true, completion: nil)

    }

    func showImagePickerController(sourceType: UIImagePickerControllerSourceType) {
        imagePickerController = UIImagePickerController()
        imagePickerController!.delegate = self
        imagePickerController!.sourceType = sourceType

        print("Set the delegate \(imagePickerController?.delegate?.isMemberOfClass(PhotoTakingHelper))")

        self.viewController.presentViewController(imagePickerController!, animated: true, completion: nil)
    }

}


extension PhotoTakingHelper: UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
        print("HELLO?")
    }

    func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) {

        viewController.dismissViewControllerAnimated(false, completion: nil)
        print("calling the callback now " )

        callback(image)

        print("Finished calling the callback")
    }


}

I've checked iPhone: UIImagePickerControllerDelegate methods not Invoked? and a similar problem and many more but none have solved the issue.

I've realized that none of the delegate methods are invoked as when I run through the program on the simulator and choose an image in the photo library, the console only prints.

Set the delegate Optional(true)

Community
  • 1
  • 1
stringRay2014
  • 636
  • 1
  • 11
  • 29
  • I think your imagePickerController is released before the delegate method call...just try to make it global...i mean declare as property – Mahendra Oct 29 '15 at 05:00
  • yes i do but i don't have it in the code sample , ill add it now to prevent confusion – stringRay2014 Oct 29 '15 at 16:36

1 Answers1

8

You're creating a PhotoTakingHelper but you're not keeping a reference to it. That is, you're doing something like this:

// In your view controller

@IBAction func pickImageButtonWasTapped() {
    _ = PhotoTakingHelper(viewController: self) { image in
        print("Callback!")
    }
}

The UIImagePickerController keeps only a weak reference to its delegate, which is not enough to keep it alive, so you have to keep a strong reference to it. You could do it by storing the helper in an instance variable of your view controller, like this:

// In your view controller

var helper: PhotoTakingHelper?

@IBAction func pickImageButtonWasTapped() {
    helper = PhotoTakingHelper(viewController: self) { image in
       print("Callback!")
    }
}

Or you could make the helper keep a reference to itself, like this:

// In PhotoTakingHelper

var me: PhotoTakingHelper?

init(viewController:UIViewController , callback:PhotoTakingHelperCallback) {
    self.viewController = viewController
    self.callback = callback
    super.init()
    me = self
    showPhotoSourceSelection()
}

And then you need to set the reference to nil when the image picker is done, to let the helper be deallocated:

extension PhotoTakingHelper: UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
        viewController.dismissViewControllerAnimated(false, completion: nil)
        callback(info[UIImagePickerControllerOriginalImage] as? UIImage)
        me = nil
    }

    func imagePickerControllerDidCancel(picker: UIImagePickerController) {
        viewController.dismissViewControllerAnimated(false, completion: nil)
        me = nil
    }

}
rob mayoff
  • 375,296
  • 67
  • 796
  • 848
  • Hey @rob , haven't tested the code yet but I was wondering if you can send me any links that further explains why the delegate has a weak reference and the whole strong/weak referencing because I find it really confusing ! THANKS!! – stringRay2014 Nov 04 '15 at 00:47
  • [Cocoa Core Competencies: Object ownership](https://developer.apple.com/library/ios/documentation/General/Conceptual/DevPedia-CocoaCore/ObjectOwnership.html#//apple_ref/doc/uid/TP40008195-CH67-SW1). — [Why are Objective-C delegates usually given the property assign instead of retain?](http://stackoverflow.com/q/918698/77567) – rob mayoff Nov 04 '15 at 01:23
  • I was having the same issue. fixed it by making PhotoTakingHelper a class property of my view controller. Thanks @robmayoff – Awais Fayyaz Jul 17 '19 at 07:33