dismiss UIImagePicker call viewDidLoad again!!

when I select an image and dismiss imagepicker Controller, the viewDidLoad of original controller also called

Answered by BurierA in 348073022

bro, i solve it by removing functions (viewWillAppear) and (viewDidDisappear)


thanx for your replies.. 🙂

That should not happen. Please provide enough information to reprocude the issue, including code and settings.

this happen with me when my original viewController is Item in tabBar controller

You should explain clearly your set up.


What is "original controller" ?

What do you mean original viewController is item in tabBarController ?


So explain the different controllers you have and give their names:

- a StartViewController, which is the Initial Vie Controller (the one with the arrow coming from "nowhere")

- a TabBarController (is it the StartViewController ?)

- ViewControllers associated to the items of TabBar: FirstViewController, SecondViewController, ThirdViewController for isntance



You say:

when I select an image and dismiss imagepicker Controller, the viewDidLoad of original controller also called

Where is the image ?

Where is the imagePicker ?

What is the original controller ?

How do you see viewDidLoad is called ?

I have tabbarController , and have five controllers associated with it as tabbarItems , in the fourth controller I have a button to open ImagePickerController to select an image from gallery and put it in the imageView in fourth Controller , and in the same fourth Controller there is a UILabel , I know the viewDidLoad call again throught I type something in the label and when I select an image and this image put in the imageView, then i noticed that the label empty, another evidence i put statement (print("loaded again")) and the statement appear after select an image and dismiss imagePickerController.

I wish I explain correctly.

thanx

Could you show the complete code of this fourth view controller ? May be you have an error in the way you dismiss the picker.

import UIKit

import SDWebImage

import Firebase

import FirebaseDatabase

import FirebaseStorage

import Reachability

import Toast_Swift

import Photos


class ProfileViewController: UIViewController,

UIImagePickerControllerDelegate,

UINavigationControllerDelegate {


@IBOutlet weak var widthOfUpdateButton: NSLayoutConstraint!


@IBOutlet weak var usernameText: UITextField!

@IBOutlet weak var currentPassword: UITextField!

@IBOutlet weak var confirmNewPasswordText: UITextField!

@IBOutlet weak var newPasswordText: UITextField!


@IBOutlet weak var emailText: UITextField!



func imageSelect(sender: UIButton)

{

let alert = UIAlertController(title: "Choose Image", message: nil, preferredStyle: .actionSheet)

alert.addAction(UIAlertAction(title: "Camera", style: .default, handler: { _ in

self.openCamera()

}))

alert.addAction(UIAlertAction(title: "Gallery", style: .default, handler: { _ in

self.openGallery()

}))

alert.addAction(UIAlertAction.init(title: "Cancel", style: .cancel, handler: nil))

/*If you want work actionsheet on ipad

then you have to use popoverPresentationController to present the actionsheet,

otherwise app will crash on iPad */

switch UIDevice.current.userInterfaceIdiom {

case .pad:

alert.popoverPresentationController?.sourceView = sender

alert.popoverPresentationController?.sourceRect = sender.bounds

alert.popoverPresentationController?.permittedArrowDirections = .up

default:

break

}

self.present(alert, animated: true, completion: nil)

}


func checkPermission(sender :UIButton) {

let photoAuthorizationStatus = PHPhotoLibrary.authorizationStatus()

switch photoAuthorizationStatus {

case .authorized:

self.imageSelect(sender: sender)

print("Access is granted by user")

case .notDetermined:

PHPhotoLibrary.requestAuthorization({

(newStatus) in

print("status is \(newStatus)")

if newStatus == PHAuthorizationStatus.authorized {

/* do stuff here */

self.imageSelect(sender: sender)

print("success")

}

})

print("It is not determined until now")

case .restricted:

// same same

print("User do not have access to photo album.")

case .denied:

// same same

print("User has denied the permission.")

}

}



@IBAction func chooseImage(_ sender: UIButton)

{

//check permission and after it select image

checkPermission(sender: sender)

}



func openCamera()

{

if(UIImagePickerController .isSourceTypeAvailable(UIImagePickerController.SourceType.camera)){

imagePicker.sourceType = UIImagePickerController.SourceType.camera

print("trueeeeeee")

//If you dont want to edit the photo then you can set allowsEditing to false

imagePicker.allowsEditing = true

imagePicker.delegate = self

imagePicker.allowsEditing = false

self.present(imagePicker, animated: true, completion: nil)

}

else

{

print("falseeee")

let alert = UIAlertController(title: "Warning", message: "You don't have camera", preferredStyle: .alert)

alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))

self.present(alert, animated: true, completion: nil)

}

}


func openGallery()

{

imagePicker.sourceType = UIImagePickerController.SourceType.photoLibrary

imagePicker.modalPresentationStyle = .popover

imagePicker.allowsEditing = false

imagePicker.delegate = self

self.present(imagePicker, animated: true, completion: nil)

}




@IBOutlet weak var imageProfile: UIImageView!


let imagePicker = UIImagePickerController()



var isViewLoading:Bool = false


override func viewDidLoad() {

super.viewDidLoad()

isViewLoading = true

loadEveryThing()

}



override func viewDidDisappear(_ animated: Bool) {

self.view = nil

}



override func viewWillAppear(_ animated: Bool)

{


if isViewLoading{

isViewLoading = false

}

else{

loadEveryThing()

}


}


func loadEveryThing()

{

print("loaded another time")

if let delegate = UIApplication.shared.delegate as? AppDelegate {

delegate.connectivity.stopNotifier()

}

widthOfUpdateButton.constant = self.view.frame.width * 0.4

imageProfile.layer.borderWidth = 1.0

imageProfile.layer.masksToBounds = false

imageProfile.layer.borderColor = UIColor.white.cgColor

imageProfile.layer.cornerRadius = 110 / 2

imageProfile.clipsToBounds = true

refStorage = Storage.storage().reference()

imagePicker.delegate = self

let uid = user!.uid

ref = Database.database().reference().child("Doctors").child(uid)



ref.observeSingleEvent(of: .value, with: { (snapshot) in


if let UserInfo = snapshot.value as? NSDictionary

{

self.usernameText.text = UserInfo["name"] as? String

self.emailText.text = UserInfo["email"] as? String

let url = URL(string: (UserInfo["image"] as? String)!)

self.geturl(urlComming: (UserInfo["image"] as? String)!)

self.getpassword(passwordComming: (UserInfo["password"] as? String)!)


self.imageProfile.sd_setImage(with: url , placeholderImage: UIImage(named: "waiting.jpeg"))




}

})

}



func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {

dismiss(animated: true, completion: nil)

}


func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {


if let imageSelected = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {

let imageDataStorage = imageSelected.jpegData(compressionQuality: 0.8)

print("imageDataForStorage \(String(describing: imageDataStorage))")

getImageUrlOfSelectedNewimage(imageDataStorage: imageDataStorage!)

//I set this delay( 1 second) because without it , app crashes with found nil unexpectedly error


DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute: {

self.imageProfile.contentMode = .scaleToFill //3

self.imageProfile.image = imageSelected

})

}


picker.dismiss(animated: false, completion: nil)

}


}


thanx

Accepted Answer

bro, i solve it by removing functions (viewWillAppear) and (viewDidDisappear)


thanx for your replies.. 🙂

I reformatted your code with the formetting tool (<>) to be able to reference lines


import UIKit
import SDWebImage
import Firebase
import FirebaseDatabase
import FirebaseStorage
import Reachability
import Toast_Swift
import Photos

class ProfileViewController: UIViewController,
    UIImagePickerControllerDelegate,
UINavigationControllerDelegate {

    @IBOutlet weak var widthOfUpdateButton: NSLayoutConstraint!

    @IBOutlet weak var usernameText: UITextField!
    @IBOutlet weak var currentPassword: UITextField!
    @IBOutlet weak var confirmNewPasswordText: UITextField!
    @IBOutlet weak var newPasswordText: UITextField!

    @IBOutlet weak var emailText: UITextField!


func imageSelect(sender: UIButton)
    {
        let alert = UIAlertController(title: "Choose Image", message: nil, preferredStyle: .actionSheet)
        alert.addAction(UIAlertAction(title: "Camera", style: .default, handler: { _ in
            self.openCamera()
        }))
   
        alert.addAction(UIAlertAction(title: "Gallery", style: .default, handler: { _ in
            self.openGallery()
        }))
   
        alert.addAction(UIAlertAction.init(title: "Cancel", style: .cancel, handler: nil))
   
        /*If you want work actionsheet on ipad
         then you have to use popoverPresentationController to present the actionsheet,
         otherwise app will crash on iPad */
        switch UIDevice.current.userInterfaceIdiom {
        case .pad:
            alert.popoverPresentationController?.sourceView = sender
            alert.popoverPresentationController?.sourceRect = sender.bounds
            alert.popoverPresentationController?.permittedArrowDirections = .up
        default:
            break
        }
   
        self.present(alert, animated: true, completion: nil)
    }

    func checkPermission(sender :UIButton) {
        let photoAuthorizationStatus = PHPhotoLibrary.authorizationStatus()
        switch photoAuthorizationStatus {
        case .authorized:
            self.imageSelect(sender: sender)
            print("Access is granted by user")
        case .notDetermined:
            PHPhotoLibrary.requestAuthorization({
                (newStatus) in
                print("status is \(newStatus)")
                if newStatus ==  PHAuthorizationStatus.authorized {
                    /* do stuff here */
                    self.imageSelect(sender: sender)
                    print("success")
                }
            })
            print("It is not determined until now")
        case .restricted:
            // same same
            print("User do not have access to photo album.")
        case .denied:
            // same same
            print("User has denied the permission.")
        }
    }


    @IBAction func chooseImage(_ sender: UIButton)
    {
      //check permission and after it select image
        checkPermission(sender: sender)
   
    }


    func openCamera()
    {
        if(UIImagePickerController .isSourceTypeAvailable(UIImagePickerController.SourceType.camera)){
       
            imagePicker.sourceType = UIImagePickerController.SourceType.camera
            print("trueeeeeee")
            //If you dont want to edit the photo then you can set allowsEditing to false
            imagePicker.allowsEditing = true
            imagePicker.delegate = self
            imagePicker.allowsEditing = false
            self.present(imagePicker, animated: true, completion: nil)
       
        }
        else
        {
            print("falseeee")
            let alert  = UIAlertController(title: "Warning", message: "You don't have camera", preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
            self.present(alert, animated: true, completion: nil)
        }
    }

    func openGallery()
    {
        imagePicker.sourceType = UIImagePickerController.SourceType.photoLibrary
        imagePicker.modalPresentationStyle = .popover
        imagePicker.allowsEditing = false
        imagePicker.delegate = self
        self.present(imagePicker, animated: true, completion: nil)
    }



    @IBOutlet weak var imageProfile: UIImageView!

let imagePicker = UIImagePickerController()


var isViewLoading:Bool = false
 
    override func viewDidLoad() {
        super.viewDidLoad()
        isViewLoading = true
        loadEveryThing()
    }
 
 
    override func viewDidDisappear(_ animated: Bool) {
       self.view = nil
  }
 
 
    override func viewWillAppear(_ animated: Bool)
    {

        if isViewLoading{
            isViewLoading = false
        }
        else{
            loadEveryThing()
        }

    }

    func loadEveryThing()
    {
        print("loaded another time")
     
        if let delegate = UIApplication.shared.delegate as? AppDelegate {
            delegate.connectivity.stopNotifier()
        }
     
        widthOfUpdateButton.constant = self.view.frame.width * 0.4
     
        imageProfile.layer.borderWidth = 1.0
        imageProfile.layer.masksToBounds = false
        imageProfile.layer.borderColor = UIColor.white.cgColor
        imageProfile.layer.cornerRadius = 110 / 2
        imageProfile.clipsToBounds = true
     
     
        refStorage = Storage.storage().reference()
        imagePicker.delegate = self
     
        let uid = user!.uid
        ref = Database.database().reference().child("Doctors").child(uid)


        ref.observeSingleEvent(of: .value, with: { (snapshot) in

            if let UserInfo = snapshot.value as? NSDictionary
            {
                self.usernameText.text = UserInfo["name"] as? String
                self.emailText.text = UserInfo["email"] as? String
                let url = URL(string: (UserInfo["image"] as? String)!)
                self.geturl(urlComming: (UserInfo["image"] as? String)!)
                self.getpassword(passwordComming: (UserInfo["password"] as? String)!)

                self.imageProfile.sd_setImage(with: url , placeholderImage: UIImage(named: "waiting.jpeg"))



            }
        })
     
    }
 
 
    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        dismiss(animated: true, completion: nil)
    }
 
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
     

        if let imageSelected = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
            let imageDataStorage = imageSelected.jpegData(compressionQuality: 0.8)
            print("imageDataForStorage \(String(describing: imageDataStorage))")
            getImageUrlOfSelectedNewimage(imageDataStorage: imageDataStorage!)
         
           //I set this delay( 1 second) because without it , app crashes with found nil unexpectedly error

            DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute: {
                self.imageProfile.contentMode = .scaleToFill //3
                self.imageProfile.image = imageSelected
            })
        }

        picker.dismiss(animated: false, completion: nil)
     
    }
 
}

Lines 195 to 197, the dismiss is on the viewController itself, not the picker.

I would call instead:

picker.dismiss(animated: true, completion: nil)

or

imagePicker.dismiss(animated: true, completion: nil)


I would also advise you to organize your code in a more readable matter:

- put all IBOutlets declarations together at top

- then declaration of variables (avoid scattering in the middle of code when they are global to the class)

- then code itself.

- I personnaly start by functions of lifecycle, such as viewDidLoad


And why don't you create the picker in IB and define an IBOutlet ?

You solved the problem, but that was not the real reason.


The problem was not viewWillAppear, but what you do inside ! You call for a reload everything ! It should not be here.

So probably, you thought you were calling viewDidload, but you were just calling reload. If you had put the print statement in viewDidload itself, you would have seen you were not calling viewDidLoad.

In addition, you need to call super in those methods:

You can override this method to perform additional tasks associated with dismissing or hiding the view. If you override this method, you must call

super
at some point in your implementation.


last point, in the future, when you post question, be more precise on what you see and not jump to a conclusion ;

And you should reorganize your code if you want to be able to maintain in the future.

try to add imagePicker.modalPresentationStyle = UIModalPresentationStyle.OverCurrentContext
this will fix your issue
dismiss UIImagePicker call viewDidLoad again!!
 
 
Q