2
votes

I am working on an app to assist visually impaired people to read restaurant menus, so I need a photo to be captured via a single double-tap of the screen.

I've successfully used the UIImagePickerController to take photos using the standard capture interface. In order to do this via double-tap, I have set the overlay view to a general ImageView, disabled camera controls and called the .takePicture() method. For some reason, the delegate method that handles the capturing of the image doesn't work. Can anyone please point me what I am missing?

I have commented the line on present the image picker as if it is called I can never leave it. My overlay has no buttons as the photo taking is supposed to be carried out by a double-tap.

Any assistance is greatly appreciated.

Best regards,

Andre.

Code below:

 import UIKit

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    @IBOutlet weak var debugLabel: UILabel!
    @IBOutlet var tapChangeState: UITapGestureRecognizer!

    @IBOutlet weak var imageView: UIImageView!
    var imagePicker = UIImagePickerController() // instantiates an image picker controller.

    override func viewDidLoad() {
        super.viewDidLoad()
        // setting up Image Picker
        imagePicker.delegate  = self // setup the view controller as the image picker delegate.
        imagePicker.allowsEditing = false // disable image editing by the user
        imagePicker.sourceType = UIImagePickerControllerSourceType.camera // set source as camera
        imagePicker.cameraDevice = UIImagePickerControllerCameraDevice.rear // use rear camera

        // setting up gesture recognizer
        tapChangeState.numberOfTouchesRequired = 1 // number of fingers required for change state detection
        tapChangeState.numberOfTapsRequired = 2

        debugLabel.text = "Loaded"
    }

    @IBAction func tapChangeStateDetected(_ sender: UITapGestureRecognizer) {
        imagePicker.cameraOverlayView = imageView
        imagePicker.showsCameraControls = false // disable camera controls
        imagePicker.takePicture() // takes the shot
        debugLabel.text = "Tap detected."
        //present(imagePicker, animated: true, completion: nil)
    }

    // Conforming to ControllerDelegate protocol:
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
        if let selectedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
            imageView.contentMode = .scaleAspectFill
            imageView.image = selectedImage
            debugLabel.text = "Captured"
        }
        dismiss(animated: true, completion: nil)
    }
    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        dismiss(animated: false, completion: nil)
    }
    // Controller Delegate protocol functions end here
}
1
What is the actual issue " the delegate method...doesn't work."?shallowThought
The imagePickerController is never called. The double-tap is detected, imagePicker.takePicture() is therefore called, but nothing happens. The debug label I added to the interface never gets updated to "Captured", I know that piece of code is never executed.Andre Guerra

1 Answers

3
votes

1. UIImagePickerController needs to be presented 1st before taking a picture.

present(imagePicker, animated: false) {
  self.imagePicker.takePicture()
}

2. Makes sure the "camera usage permission" is set in your Info.plist.

<key>Privacy - Camera Usage Description</key>
<string>My Awesome App requires access to your phone’s camera.</string>

3. cameraOverlayView is the view that is overlayed over the default camera UI. I believe in your example you don't want to use imageView because that is the view that is getting set with the captured image. If you set cameraOverlayView with imageView then imageViewis removed from your main view controller hierarchy. To get your example working, I removed imagePicker.cameraOverlayView = imageView from the IBAction.