I am making an app which has a news feed of images (HomeViewController). The user can tap on each image which segues to the SiteViewController which has a table view of empty data and a button that when clicked segues to ContextSheetViewController where the user can upload data of the image that they clicked on in the news feed. The user then presses upload and this data (siteCodeTextView, areaCodeTextView, trenchTextView) is saved to firebase and it dismisses back to the SiteViewController. I then want to retrieve the data value of siteCodeTextView that has just been uploaded of the image in the table view of the SiteViewController. But when I press upload in the ContextSheetViewController the error: Unexpectedly found nil while unwrapping an Optional value occurs. And my sheetId is printing nil in SiteViewController so I am not sure how to retrieve it correctly? Any help?
Here is my storyboard of relevant view controllers:
Code for SiteViewController:
class SiteViewController: UIViewController { @IBOutlet weak var tableView: UITableView! var sheets = [Sheet]() var users = [User]() var sheetId: String! var postId: String! override func viewDidLoad() { super.viewDidLoad() tableView.dataSource = self loadSheets() print(postId) print(sheetId) } func loadSheets() { Api.Sheet.REF_SHEETS.child(self.postId!).observe(.childAdded, with: { snapshot in Api.Sheet.observeSheets(withSheetId: snapshot.key, completion: { sheet in // self.fetchUser(uid: sheet.uid!, completed: { print("sheet id: \(sheet.id)") print("sheet uid: \(sheet.uid)") self.sheets.append(sheet) self.tableView.reloadData() // }) }) }) } func fetchUser(uid: String, completed: @escaping () -> Void ) { Api.User.observeUser(withId: uid, completion: { user in self.users.append(user) completed() }) } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "SheetSegue" { let sheetVC = segue.destination as! SheetViewController let sheetId = sender as! String sheetVC.sheetId = sheetId } } } extension SiteViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return sheets.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "SheetCell", for: indexPath) as! SiteTableViewCell let sheet = sheets[indexPath.row] print("sheet id: \(sheet.id)") print("sheet uid: \(sheet.uid)") // let user = users[indexPath.row] // cell.user = user cell.sheet = sheet cell.delegate = self return cell } } extension SiteViewController: SiteTableViewCellDelegate { func goToSheetVC(sheetId: String) { performSegue(withIdentifier: "SheetSegue", sender: sheetId) } } Code for ContextSheetViewController:
class ContextSheetViewController: UIViewController { @IBOutlet weak var siteCodeTextView: UITextField! @IBOutlet weak var areaCodeTextView: UITextField! @IBOutlet weak var trenchTextView: UITextField! @IBOutlet weak var uploadArtefactImage: UIImageView! @IBOutlet weak var artefactImageView: UIImageView! var selectedImage: UIImage? var postId: String! override func viewDidLoad() { super.viewDidLoad() let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.handleSelectPhoto)) uploadArtefactImage.addGestureRecognizer(tapGesture) uploadArtefactImage.isUserInteractionEnabled = true } @objc func handleSelectPhoto() { let pickerController = UIImagePickerController() pickerController.delegate = self present(pickerController, animated: true, completion: nil) } @IBAction func uploadButton_TouchUpInside(_sender: Any) { if let profileImg = self.artefactImageView.image, let imageData = UIImageJPEGRepresentation(profileImg, 0.1) { let photoIdString = NSUUID().uuidString print(photoIdString) let storageRef = Storage.storage().reference(forURL: Config.STORAGE_ROOF_REF).child("sheets").child(photoIdString) storageRef.putData(imageData, metadata: nil, completion: { (metadata, error) in if error != nil { ProgressHUD.showError(error!.localizedDescription) return } let photoUrl = metadata?.downloadURL()?.absoluteString self.sendDataToDatabase(photoUrl: photoUrl!) }) } else { ProgressHUD.showError("Sheet Image can not be empty!") } } func sendDataToDatabase(photoUrl: String) { // let ref = Database.database().reference() let sheetsReference = Api.Sheet.REF_SHEETS // let sheetsReference = ref.child("sheets") let newSheetId = sheetsReference.childByAutoId().key let newSheetReference = sheetsReference.child(newSheetId) guard let currentUser = Auth.auth().currentUser else { return } let currentUserId = currentUser.uid newSheetReference.setValue(["uid": currentUserId, "photoUrl": photoUrl, "siteCodeTextView": siteCodeTextView.text!, "areaCodeTextView": areaCodeTextView.text!, "trenchTextView": trenchTextView.text!], withCompletionBlock: { (error, ref) in if error != nil { ProgressHUD.showError(error!.localizedDescription) return } let postSheetRef = Api.Sheet.REF_SHEETS.child(self.postId!).child(newSheetId) // let postSheetRef = Api.Sheet.REF_SHEETS.child("post-sheets").child(self.postId).child(newSheetId) postSheetRef.setValue(true, withCompletionBlock: { (error, ref) in if error != nil { ProgressHUD.showError(error!.localizedDescription) return } }) ProgressHUD.showSuccess("Success") self.clean() self.navigationController?.popViewController(animated: true) }) } func clean() { self.siteCodeTextView.text = "" self.uploadArtefactImage.image = UIImage(named: "upload") self.artefactImageView.image = UIImage(named: "image") } } extension ContextSheetViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate { func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) { print("did Finish Picking Media") if let image = info["UIImagePickerControllerOriginalImage"] as? UIImage{ artefactImageView.image = image // selectedImage = image // uploadArtefactImage.image = image } dismiss(animated: true, completion: nil) } } Code for SiteTableViewCell:
protocol SiteTableViewCellDelegate { func goToSheetVC(sheetId: String) } class SiteTableViewCell: UITableViewCell { @IBOutlet weak var profileImageView: UIImageView! @IBOutlet weak var siteSheetLabel: UILabel! @IBOutlet weak var nameLabel: UILabel! var delegate: SiteTableViewCellDelegate? var sheet: Sheet? { didSet { updateView() } } var user: User? { didSet { setupUserInfo() } } func updateView() { siteSheetLabel.text = sheet?.siteCodeTextView } override func awakeFromNib() { super.awakeFromNib() // Initialization code } func setupUserInfo() { nameLabel.text = user?.username if let photoUrlString = user?.profileImageUrl { let photoUrl = URL(string: photoUrlString) profileImageView.sd_setImage(with: photoUrl, placeholderImage: UIImage(named: "placeholderImg")) } } override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.siteSheetLabel_TouchUpInside)) siteSheetLabel.addGestureRecognizer(tapGesture) siteSheetLabel.isUserInteractionEnabled = true } @objc func siteSheetLabel_TouchUpInside() { print(sheet?.id) if let id = sheet?.id{ delegate?.goToSheetVC(sheetId: id) } } override func prepareForReuse() { super.prepareForReuse() profileImageView.image = UIImage(named: "placeholderImg") } } 