Vladyslav Zavalykhatko
Vladyslav Zavalykhatko

Reputation: 17364

UIImagePickerController Use Photo / Retake buttons don't work

I use default UIImagePickerController for taking photos / choosing them from a library. At some point, I present other ViewController over UIImagePickerController for customization of chosen photo. If a user selects Cancel option, I want to get him back to image choosing screen - in a case of camera source to screen with Use Photo / Retake buttons. After dismissing ViewController with customization buttons don't work (they work before).

I would rather not use AVFoundation here.

Here is some related code:

let storyBuilder = StoryBuilderViewController.storyboardController()

storyBuilder.delegate = self

photoPickerController.present(storyBuilder, animated: true)

This way I'm presenting my customization screen.

func resetButtonTapped(_ storyBuilder: StoryBuilderViewController) {
    storyBuilder.dismiss(animated: true)
}

This code runs after dismissing.

So, nothing special, but buttons stop working

View Hierarchy looks like this:

View Hierarchy

So, there is nothing over this screen. Buttons properties isEnabled set to true. UIImagePickerController isn't nil. isUserInteractionEnabled is true

I've created a simple project with this error. It doesn't work either. Also, I've just had a case, when camera stops work entirely, even after app restart, with logs full of errors. Only restart of my phone helps.

More description

I have a start screen - RootViewController. I need to present UIImagePickerController with a camera over it. After a user makes a photo I need to present another controller - EditViewController (not dismissing UIImagePickerController, so if a user wants to take another photo - he just goes back). I do it like this:

picker(editController, animated: true) //picker - UIImagePickerController, editController - edit controller

As I said before, my user can go back - and here is a problem - if I dismiss editController, buttons on UIImagePickerController don't work.

Please, ask some questions, I don't understand, why is it hard to get my issue correctly.

Upvotes: 2

Views: 5937

Answers (2)

Aanchal Chaurasia
Aanchal Chaurasia

Reputation: 629

I had Checked your demo code and make certain changes to make it work as you wants it. 1) Please check ViewController class code.

class ViewController: UIViewController {
    fileprivate var photoPickerController = UIImagePickerController()
    let notificationIdentifier: String = "StartCamera"

    override func viewDidLoad() {
        // Register to receive notification
        NotificationCenter.default.addObserver(self, selector: #selector(ViewController.cameraSetUp), name: NSNotification.Name(rawValue: notificationIdentifier), object: nil)
    }

    func cameraSetUp(){
        photoPickerController.sourceType = .camera
        photoPickerController.cameraDevice = .front
        photoPickerController.delegate = self
        present(photoPickerController, animated: true)

    }
    @IBAction func showCamera(_ sender: Any) {
        cameraSetUp()
    }
}

extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
        guard let storyboard = storyboard else {return}
        let viewController = storyboard.instantiateViewController(withIdentifier: "EditingViewController")
        picker.dismiss(animated: true)
        present(viewController, animated: true)
    }

    public func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        picker.dismiss(animated: true)
    }
}

2) EditingViewController class code

class EditingViewController: UIViewController {
    let notificationIdentifier: String = "StartCamera"

    @IBAction func dismissButtonTapped(_ sender: Any) {
        // Post a notification
        dismiss(animated: true)
        NotificationCenter.default.post(name: NSNotification.Name(rawValue: notificationIdentifier), object: nil)
    }
}

Upvotes: 5

Rashwan L
Rashwan L

Reputation: 38833

So your problem is that you´re stacking your controllers. You don´t need to do that. Another thing is that your cancel button in your viewController has no usage. You do also need to hold a reference of the UIImagePickerController making it an instance property of your view controller and present it.

Code below:

import UIKit

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    let photoPickerController = UIImagePickerController()

    override func viewDidLoad() {
        super.viewDidLoad()
        photoPickerController.delegate = self
    }


    @IBAction func cancelBtnTapped(_ sender: UIButton) {
        showFrontCamera()
    }

    @IBAction func showCamera(_ sender: Any) {
        showFrontCamera()
    }

    func showFrontCamera() {
        photoPickerController.sourceType = .camera
        photoPickerController.cameraDevice = .front
        present(photoPickerController, animated: true)
    }

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
        print("didFinishPickingMediaWithInfo")
        if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
            // your image
        }

        picker.dismiss(animated: true){
            // any code after dismissing the controller
        }
    }

    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        print("imagePickerControllerDidCancel")
        picker.dismiss(animated: true){
            // any code after dismissing the controller
        }
    }
}

Upvotes: 1

Related Questions