I have a very strange issue occurring that I have not seen before while developing. It makes it very difficult to troubleshoot due to the fact the app is not crashing and there is no erroneous debug output in the console window.
I have an edit user profile ViewController. On this page it displays the users first and last name, e-mail and phone number, along with a picture. This is all being pulled from Firebase and is working fine. The "picture" you see is an actual JPG that is "uploaded" when someone creates an account, this way the photo URL is stored in their database and I can retrieve it to display a photo. In theory, when "editing" a profile, the user would see a real pic in there, and "change" it with the one they are taking or upload.
The issue I am having is that when I finish selecting a picture from the gallery or take one from the camera, it correctly dismisses the camera or gallery, but the "tableviewcell" dissapears, and I do not see the picture or the text. Oddly enough, the text fields remain that are not part of the table. The intent is to have the pic that is "taken" temporarily appear in the UIImage view (which lives in the tableviewcell) and then when the user hits "save", it will upload to FireBase (that part I know how to do). That VC then gets dismissed and the data on in ProfileVC is reloaded from FireBase with the new pic.
I have the firebase part down as well as I correctly (I think) coded the image picker, but there has to be something I am missing as to why the temporary image is not displaying.
As an additional troubleshooting step I commented out the line: self.editProfileTable.reloadData() under the function imagePickerContoller in the EditProfileVC.swift file. When I did that, after hitting "chose Photo" that view dismisses and it goes right back to the Before Update Picture picture below. It has to be something with the table, but I am just not seeing it.
I have included all relevant code below.
EditProfileVC.swift
import UIKit
import Firebase
import FirebaseAuth
import FirebaseDatabase
import FirebaseStorage
class EditProfileVC: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate, Alertable, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
var delegate : ImagePickerDelegate?
var tempImage : UIImage?
var imagePicker : UIImagePickerController?
@IBOutlet var editProfileTable: UITableView!
@IBOutlet var editEmailTextField: UITextField!
@IBOutlet var editMobileTextField: UITextField!
var editProfileInfo = [EditProfileModel]()
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return editProfileInfo.count
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "editprofilecell", for: indexPath) as! EditProfileTableViewCell
let editprofile: EditProfileModel
editprofile = editProfileInfo[indexPath.row]
cell.firstNameLabel.text = editprofile.firstname
cell.lastNameLabel.text = editprofile.lastname
cell.emailLabel.text = editprofile.email
cell.mobileLabel.text = editprofile.mobile
cell.tapButton = {(user) in
self.pickImage()
}
if tempImage == nil {
DataService.instance.REF_USERS.observeSingleEvent(of: .value, with: { (snapshot) in
if let snapshot = snapshot.children.allObjects as? [DataSnapshot] {
self.editProfileInfo.removeAll()
for snap in snapshot {
if snap.key == Auth.auth().currentUser?.uid {
let imageUrl = snap.childSnapshot(forPath: "userPhoto").value
// print(imageUrl)
let storage = Storage.storage()
let ref = storage.reference(forURL: imageUrl as! String)
ref.getData(maxSize: 1 * 1024 * 1024) { data, error in
if error != nil {
// Uh-oh, an error occurred!
} else {
cell.updateProfileImage.image = UIImage(data: data!)
}
}
}
}
}
})
}
delegate?.pickImage()
cell.updateProfileImage.image = tempImage
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
editEmailTextField.delegate = self
editMobileTextField.delegate = self
view.bindtoKeyboard()
imagePicker = UIImagePickerController()
let tap = UITapGestureRecognizer(target: self, action: #selector(handleScreenTap(sender:)))
self.view.addGestureRecognizer(tap)
DataService.instance.REF_USERS.observeSingleEvent(of: .value, with: { (snapshot) in
if let snapshot = snapshot.children.allObjects as? [DataSnapshot] {
self.editProfileInfo.removeAll()
for snap in snapshot {
if snap.key == Auth.auth().currentUser?.uid {
let profileObject = snap.value as? [String: AnyObject]
let profileFirstName = profileObject?["first_name"]
let profileLastName = profileObject?["last_name"]
let profileMobile = profileObject?["mobile_number"]
let profileEmail = Auth.auth().currentUser?.email
let editprofile = EditProfileModel(firstname: profileFirstName as! String?, lastname: profileLastName as! String?, email: profileEmail , mobile: profileMobile as! String?)
self.editProfileInfo.append(editprofile)
}
self.editProfileTable.reloadData()
}
}
})
delegate?.pickImage()
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
@objc func handleScreenTap(sender: UITapGestureRecognizer) {
self.view.endEditing(true)
}
func pickImage() {
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self
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))
self.present(alert, animated: true, completion: nil)
// let imagePicker = UIImagePickerController()
// imagePicker.delegate = self
// imagePicker.sourceType = UIImagePickerController.SourceType.photoLibrary
// imagePicker.allowsEditing = false
// self.present(imagePicker, animated: true, completion: nil)
}
func openCamera()
{
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.camera) {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerController.SourceType.camera
imagePicker.allowsEditing = false
self.present(imagePicker, animated: true, completion: nil)
}
else
{
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()
{
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.photoLibrary){
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.allowsEditing = true
imagePicker.sourceType = UIImagePickerController.SourceType.photoLibrary
self.present(imagePicker, animated: true, completion: nil)
}
else
{
let alert = UIAlertController(title: "Warning", message: "You don't have perission to access gallery.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]){
if let pickedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
tempImage = pickedImage
self.editProfileTable.reloadData()
dismiss(animated: true, completion: nil)
// imageViewPic.image = pickedImage
}
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
EditProfileModel.swift
class EditProfileModel {
var firstname: String?
var lastname: String?
var email: String?
var mobile: String?
init(firstname: String?, lastname: String?, email: String?, mobile: String?){
self.firstname = firstname
self.lastname = lastname
self.email = email
self.mobile = mobile
}
}
EditProfileTableViewCell.swift
import UIKit
import Foundation
var delegate : ImagePickerDelegate?
class EditProfileTableViewCell: UITableViewCell {
@IBOutlet var updateProfileImage: UIImageView!
@IBOutlet var firstNameLabel: UILabel!
@IBOutlet var lastNameLabel: UILabel!
@IBOutlet var emailLabel: UILabel!
@IBOutlet var mobileLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
@IBAction func btdDetailsClick(_ sender: Any) {
tapButton?(self)
delegate?.pickImage()
}
var tapButton: ((UITableViewCell) -> Void)?
}
ImagePicker.swift
import UIKit
import Foundation
protocol ImagePickerDelegate {
func pickImage()
}