when I select an image and dismiss imagepicker Controller, the viewDidLoad of original controller also called
dismiss UIImagePicker call viewDidLoad again!!
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
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.
this will fix your issue