Search code examples
iosswiftswift3uiimagepickercontroller

Swift - Is there a way to present an AlertController while the camera is active?


I am using Swift 3, Xcode 8.2.

I currently have an application where I have the user open up the camera to take a picture. Once the camera is opened, I want there to be an alert box that appears that gives the user some information. The user can click "Done" before control is returned to the camera again.

Here is my code:

func openCameraAction() {


    // Check if the camera is available on the device as a source type
    if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera) {

        // declare a variable of image picker controller
        let imagePicker = UIImagePickerController()

        // set its delegate, set its source type
        imagePicker.delegate = self
        imagePicker.sourceType = UIImagePickerControllerSourceType.camera

        // tell our image picker to not edit a captured picture
        // which means that we won’t get the black screen with
        // a square frame right after taking a photo.
        imagePicker.allowsEditing = false

        // present the camera controller, it will show up from the
        // bottom of the screen, which is the default iOS animation
        // for opening new screens.
        self.present(imagePicker, animated: true, completion: nil)


    }
}

func displayInstructions() {

    let instructionController = UIAlertController(title: "Photo Instructions", message: "Some instruction here", preferredStyle: .alert)

    let actionDone = UIAlertAction(title: "Done", style: .cancel) { (action:UIAlertAction) in
        //This is called when the user presses the done button.
        print("You've pressed the done button");
    }


    //Add the buttons
    instructionController.addAction(actionDone)

    //Present the instruction controller
    self.present(instructionController, animated: true, completion: nil)
}

I've tried setting the completion field in openCameraAction to call the method displayInstruction but quickly realized that I am not allowed to present things in a nested way. I believe presents must happen from the root view controller level, correct?

Attempt to present ... on ... whose view is not in the window hierarchy!

However, is there some way that I can achieve this effect? Do some sort of nested presents?

Thank you for your help.

EDIT

I looked at the other question and am still a bit confused. I grabbed a snippet of code from one of the other answers and am having a hard time figuring out how to integrate into my code.

        var rootViewController = UIApplication.shared.keyWindow?.rootViewController
        if let navigationController = rootViewController as? UINavigationController {
            rootViewController = navigationController.viewControllers.first
        }
        if let tabBarController = rootViewController as? UITabBarController {
            rootViewController = tabBarController.selectedViewController
        }
        rootViewController?.present(alertController, animated: true, completion: nil)

Do I include the above code in the openCameraAction or displayInstruction function?


Solution

  • you should have to present UIAlertController on UIImagePickerController. I have modified your code. See below code.

    func openCameraAction() 
    {
        // Check if the camera is available on the device as a source type
        if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera) 
        {
    
            // declare a variable of image picker controller
            let imagePicker = UIImagePickerController()
    
            // set its delegate, set its source type
            imagePicker.delegate = self
            imagePicker.sourceType = UIImagePickerControllerSourceType.camera
    
            // tell our image picker to not edit a captured picture
            // which means that we won’t get the black screen with
            // a square frame right after taking a photo.
            imagePicker.allowsEditing = false
    
            // present the camera controller, it will show up from the
            // bottom of the screen, which is the default iOS animation
            // for opening new screens.
            self.present(imagePicker, animated: true, completion: { 
    
              let instructionController = UIAlertController(title: "Photo Instructions", message: "Some instruction here", preferredStyle: .alert)
    
              let actionDone = UIAlertAction(title: "Done", style: .cancel)  {(action:UIAlertAction) in
                //This is called when the user presses the done button.
                print("You've pressed the done button");
              }
    
              //Add the buttons
              instructionController.addAction(actionDone)
    
              //Present the instruction controller
              imagePicker.present(instructionController, animated: true, completion: nil)
    
           })
       }
    }
    

    I have tried above code. It is working correctly. Try it!