swift read write to firestore documents and collections - swift

from the IOS app i'm trying to update with new data 5 different "collection" in Firestore. I'm able to do that but to 1 collection only. I can't figure it out how to push the updates to all 5 collections at once. Any help is greatly appreciated.
import UIKit
import Firebase
class itemDataViewController: UIViewController {
#IBOutlet var itemLabels: [UILabel]!
#IBOutlet weak var testLabel: UILabel!
#IBOutlet weak var firstItemField: UITextField!
#IBOutlet weak var secondItemField: UITextField!
#IBOutlet weak var thirdItemField: UITextField!
#IBOutlet weak var fourthItemField: UITextField!
#IBOutlet weak var fithItemField: UITextView!
var docRef: DocumentReference!
var infoListener: ListenerRegistration!
#IBAction func updateData(_ sender: Any) {
guard let firstItemText = firstItemField.text, !firstItemText.isEmpty else { return }
guard let secondItemText = secondItemField.text, !secondItemText.isEmpty else { return }
guard let thirdItemText = thirdItemField.text, !thirdItemText.isEmpty else { return }
guard let fourthItemText = fourthItemField.text, !fourthItemText.isEmpty else { return }
guard let fithItemText = fithItemField.text, !fithItemText.isEmpty else { return }
let dataToSave: [String: Any] = ["firstItem": firstItemText]
docRef.setData(dataToSave) { (error) in
if let error = error {
print("Oh no! Could not save: \(error.localizedDescription)")
} else {
print("Data Saved")
}
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
infoListener = docRef.addSnapshotListener { (docSnapshot, error) in
guard let docSnapshot = docSnapshot, docSnapshot.exists else { return }
let myData = docSnapshot.data()
let firstItemUpdate = myData?["firstItem"] as? String ?? ""
self.firstItemField.text = "\(firstItemUpdate)"
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillAppear(animated)
infoListener.remove()
}
override func viewDidLoad() {
super.viewDidLoad()
docRef = Firestore.firestore().document("2/firstItem")
(itemLabels as NSArray).setValue(10, forKey: "cornerRadius")
// Do any additional setup after loading the view.
}
}

Related

Force unwrapping nil optional for UIImageView when transitioning to view controller

I'm running into an error when transitioning to view controllers by overriding the built-in prepare() function in Swift. I have a UIImageView for backgrounds on my screens. Here is the code for two of the view controllers in question.
import UIKit
import FirebaseAuth
class HomeVC: UIViewController {
#IBOutlet weak var signOutButton: UIButton!
#IBOutlet weak var backgroundImageView: UIImageView!
#IBOutlet weak var friendsNavButton: UIButton!
#IBOutlet weak var homeNavButton: UIButton!
#IBOutlet weak var profileNavButton: UIButton!
#IBOutlet weak var bumpButton: UIButton!
#IBOutlet weak var welcomeLabel: UILabel!
#IBOutlet weak var doNotDisturbLabel: UILabel!
#IBOutlet weak var doNotDisturbButton: UIButton!
var userName = ""
var dndIsOn: Bool = false
#IBAction func dndToggled(_ sender: Any) {
dndIsOn = !dndIsOn
User.current.available = !dndIsOn
FirestoreService.db.collection(Constants.Firestore.Collections.users).document(User.current.uid).updateData([Constants.Firestore.Keys.available : !dndIsOn])
if dndIsOn {
print("DND is on!")
setupDNDUI()
} else if !dndIsOn {
print("DND is off!")
setupActiveUI()
}
}
#IBAction func signOutTapped(_ sender: Any) {
let firAuth = Auth.auth()
do {
try firAuth.signOut()
} catch let signOutError as NSError {
print ("Error signing out: %#", signOutError)
}
print("Successfully signed out")
}
#IBAction func bumpTapped(_ sender: Any) {
self.performSegue(withIdentifier: Constants.Segues.toCall, sender: self)
}
#IBAction func friendsNavTapped(_ sender: Any) {
self.performSegue(withIdentifier: Constants.Segues.toFriends, sender: self)
}
#IBAction func profileNavTapped(_ sender: Any) {
let nav = self.navigationController //grab an instance of the current navigationController
DispatchQueue.main.async { //make sure all UI updates are on the main thread.
nav?.view.layer.add(CATransition().segueFromLeft(), forKey: nil)
nav?.pushViewController(ProfileVC(), animated: false)
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.setNavigationBarHidden(true, animated: true)
self.backgroundImageView.contentMode = UIView.ContentMode.scaleAspectFill
doNotDisturbLabel.isHidden = true
if !userName.isEmpty {
welcomeLabel.text = "Welcome Back, " + userName + "!"
} else {
welcomeLabel.text = ""
}
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return .darkContent
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let friendsVC = segue.destination as? FriendsVC else {
return
}
FirestoreService.db.collection(Constants.Firestore.Collections.users).document(User.current.uid).getDocument { (snapshot, err) in
if let err = err {
print(err.localizedDescription)
} else {
let data = snapshot!.data()!
let requests = data[Constants.Firestore.Keys.requests] as? [String]
if let requests = requests {
friendsVC.requests = requests
}
}
}
}
class FriendsVC: UIViewController {
//var friends: [Friend] = User.current.friends
var friends: [User] = []
var requests: [String]?
#IBOutlet weak var requestsNumberLabel: UILabel!
#IBOutlet weak var backgroundImageView: UIImageView!
#IBOutlet weak var friendRequestsButton: UIButton!
#IBOutlet weak var homeNavButton: UIButton!
#IBOutlet weak var friendsTitle: UILabel!
#IBOutlet weak var friendTableView: UITableView!
#IBOutlet weak var addFriendButton: UIButton!
#IBOutlet weak var tableViewTopConstraint: NSLayoutConstraint!
#IBAction func friendRequestsTapped(_ sender: Any) {
self.performSegue(withIdentifier: Constants.Segues.toRequests, sender: self)
}
#IBAction func homeNavTapped(_ sender: Any) {
let nav = self.navigationController //grab an instance of the current navigationController
DispatchQueue.main.async { //make sure all UI updates are on the main thread.
nav?.view.layer.add(CATransition().segueFromLeft(), forKey: nil)
nav?.pushViewController(HomeVC(), animated: false)
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.setNavigationBarHidden(true, animated: true)
backgroundImageView.contentMode = UIView.ContentMode.scaleAspectFill
friendTableView.backgroundView?.backgroundColor = .white
friendsTitle.isHidden = false
UserService.getUserArray(uids: User.current.friendUids, completion: { (users) in
guard let users = users else {
print("User has no friends")
return
}
self.friends = users
self.friendTableView.reloadData()
})
guard let requests = self.requests else {
friendRequestsButton.isHidden = true
requestsNumberLabel.isHidden = true
self.tableViewTopConstraint.constant = 0
return
}
requestsNumberLabel.text = requests.count.description
// Do any additional setup after loading the view.
friendTableView.delegate = self
friendTableView.dataSource = self
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let homeVC = segue.destination as? HomeVC {
homeVC.userName = User.current.firstName
} else if let requestsVC = segue.destination as? RequestsVC {
UserService.getUserArray(uids: self.requests!) { (requesters) in
if let requesters = requesters {
requestsVC.requesters = requesters
}
}
}
}
}
When my app loads into the home screen, there is no problem, and when a button is tapped to transition to FriendsVC, there is no problem. However, when I try to initiate the transition from HomeVC to ProfileVC or from FriendVC to HomeVC, I get the error: "Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value" at the self.backgroundImageView.contentMode = UIView.ContentMode.scaleAspectFill lines in my viewDidLoad methods. These segues have something in common in that these are the ones where I override the prepare() function, but I'm not sure what I'm doing wrong

Sigbart error during prepare for segue/unwind segue

I have an app where it is a marketplace and when you click on a product, it opens a detail view controller passing the data to display on the DetailVC. Additionally, inside the DetailVC, if you click on a button to claim the product, it segues to another VC to finalize the transaction.
In the DetailVC, there is a back button which is an unwind segue back to the main marketplace VC. Inside the TransactionVC, there is a cancel button which takes you back to the DetailVC.
When I am clicking the backButton in the DetailVC to take me back to the main market VC but I am getting a SIGBART Error and this :
020-07-15 09:05:23.707490-0500 evolutionatx[707:141952] Could not cast value of type 'evolutionatx.MarketplaceViewController' (0x1032c7868) to 'evolutionatx.PopUpPurchaseViewController' (0x1032c7ba8).
Here is the code for the DetailVC
import UIKit
import iCarousel
import CoreData
class MarketDetailViewController: UIViewController, UIScrollViewDelegate, iCarouselDelegate, iCarouselDataSource {
var productImageArray = [UIImage]()
var productVideo = String()
var pointsToPurchase = String()
var productName = String()
var productDescription = String()
var companyLogo = UIImage()
var companyWebsite = String()
var additionalProductImage = [UIImage]()
var companyName = String()
var promoCODE = String()
var buyLink = String()
var slides:[Slide] = [];
//IB
#IBOutlet weak var productNameLabel: UILabel!
#IBOutlet weak var productPriceLabel: UILabel!
#IBOutlet weak var productDescLabel: UILabel!
#IBOutlet weak var claimButton: UIButton!
#IBOutlet weak var imgScrollView: UIScrollView!
#IBOutlet weak var websiteButton: UIButton!
#IBOutlet weak var pageControl: UIPageControl!
#IBOutlet weak var logoDisplay: UIImageView!
#IBOutlet weak var carouselView: iCarousel!
#IBOutlet weak var otherProductslabe: UILabel!
var carouselImages = [UIImage]()
var evoCoin = Int()
override func awakeFromNib() {
super.awakeFromNib()
carouselImages = productImageArray
}
override func viewDidLoad() {
super.viewDidLoad()
valueSetter()
imgScrollView.delegate = self
slides = createSlides()
setupSlideScrollView(slides: slides)
pageControl.numberOfPages = slides.count
pageControl.currentPage = 0
view.bringSubviewToFront(pageControl)
}
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let pageIndex = round(scrollView.contentOffset.x/view.frame.width)
pageControl.currentPage = Int(pageIndex)
let maximumHorizontalOffset: CGFloat = scrollView.contentSize.width - scrollView.frame.width
let currentHorizontalOffset: CGFloat = scrollView.contentOffset.x
// vertical
let maximumVerticalOffset: CGFloat = scrollView.contentSize.height - scrollView.frame.height
let currentVerticalOffset: CGFloat = scrollView.contentOffset.y
let percentageHorizontalOffset: CGFloat = currentHorizontalOffset / maximumHorizontalOffset
let percentageVerticalOffset: CGFloat = currentVerticalOffset / maximumVerticalOffset
}
#IBAction func claimProduct(_ sender: Any) {
print("tap rec")
claimProductandPurchase()
}
func claimProductandPurchase(){
evoCOiner()
if(evoCoin >= Int(pointsToPurchase)!){
print("Transaction Successful")
performSegue(withIdentifier: "proceedQuestion", sender: self)
}
else{
showToast(controller: self, message: "Insufficient EvoCoins", seconds: 0.5)
}
}
func showToast(controller: UIViewController, message : String, seconds: Double) {
let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert)
alert.view.backgroundColor = UIColor.black
alert.view.alpha = 0.6
alert.view.layer.cornerRadius = 15
controller.present(alert, animated: true)
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + seconds) {
alert.dismiss(animated: true)
}
}
func evoCoiner(){
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "EvoCoins")
request.returnsObjectsAsFaults = false
do{
let result = try context.fetch(request)
for data in result as! [NSManagedObject]
{
evoCoin = data.value(forKey: "evoCoins") as! Int
}
}catch{
print("Failed")
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let detailController = segue.destination as! PopUpPurchaseViewController
detailController.ppromo = promoCODE
detailController.link = buyLink
detailController.coinToPurchase = Int(pointsToPurchase)!
}
//This is the unwind used by the transaction back button
#IBAction func unwindToItem(segue: UIStoryboardSegue) {
}
}
Here is the code in the transaction VC
import UIKit
import AMTabView
import CoreData
class MarketplaceViewController: UIViewController, TabItem {
#IBOutlet weak var sView: UIView!
#IBOutlet weak var evoCoinLabe: UILabel!
//For the sake of simplicity I only kept the Unwind functions
//MARK: - UNWIND FUNCTIONS
#IBAction func unwindToMainMarketView(segue: UIStoryboardSegue) {
}
}
How can I fix this error?
Please advise if my question was not clear or properly phrased (if so, sorry I am pretty new to all of this)
As #matt already said in his comment and the error clearly states, you cannot cast a MarketplaceViewController to a PopUpPurchaseViewController.
Furthermore instead of doing a forced cast, always look for a safe one like below. Doing so will prevent crashes.
if let detailController = segue.destination as? PopUpPurchaseViewController {
...
}
else {
// log failed to cast
}

How can I use a variable outside a function, im looking to get the documentdata() variable into the answer buttons

Since I call the getdata() in the viewDidLoad function I cant get the variable documentdata out. Im trying to use the documentdata's data for the button. I know I need a return type for the get data as well, but I cant seem to get that. TLDR: im trying to get the value documentdata into another a whole other function. Thank you in advance for anyone who responded.
import UIKit
import Firebase
import FirebaseFirestore
class QuizViewController: UIViewController {
#IBOutlet weak var questionLabel: UILabel!
#IBOutlet weak var answerButtonTwo: UIButton!
#IBOutlet weak var answerButtonOne: UIButton!
#IBOutlet weak var answerButtonThree: UIButton!
#IBOutlet weak var answerButtonFour: UIButton!
#IBOutlet weak var displayAnswerChoice: UILabel!
var isrun = false
var documentdata:[String:Any] = ["":""]
override func viewDidLoad(){
super.viewDidLoad()
setupElements()
getData()
}
func setupElements(){
answerButtonOne.setTitle("", for:.normal)
answerButtonTwo.setTitle("", for:.normal)
answerButtonThree.setTitle("", for:.normal)
answerButtonFour.setTitle("", for:.normal)
questionLabel.text = ""
displayAnswerChoice.text = ""
}
func getData() {
let db = Firestore.firestore()
db.collection("quizs").document("basketballQuiz").getDocument { (document,error) in
if error == nil{
print("cant get data")
}
if document != nil && document!.exists{
let documentdata = document!.data()
self.questionLabel.text = documentdata?["Question"] as? String
self.answerButtonOne.setTitle(documentdata?["Answer1"] as? String, for:.normal)
self.answerButtonTwo.setTitle(documentdata?["Answer2"] as? String, for:.normal)
self.answerButtonThree.setTitle(documentdata?["Answer3"] as? String, for:.normal)
self.answerButtonFour.setTitle(documentdata?["Answer4"] as? String, for:.normal)
}
}
}
#IBAction func AnswerOneTap(_ sender: Any) {
let rightAnswer:Int = documentdata["correctAnswer"] as! Int
if (rightAnswer == 1){
displayAnswerChoice.text = "Correct"
displayAnswerChoice.backgroundColor = UIColor(named: "Green")
}
}
#IBAction func AnswerTwoTap(_ sender: Any) {
let rightAnswer:Int = documentdata["correctAnswer"] as! Int
if (rightAnswer == 2){
displayAnswerChoice.text = "Correct"
displayAnswerChoice.backgroundColor = UIColor(named: "Green")
}
}
#IBAction func AnswerThreeTap(_ sender: Any) {
let rightAnswer:Int = documentdata["correctAnswer"] as! Int
if (rightAnswer == 3){
displayAnswerChoice.text = "Correct"
displayAnswerChoice.backgroundColor = UIColor(named: "Green")
}
}
#IBAction func AnswerFourTap(_ sender: Any) {
let rightAnswer:Int = documentdata["correctAnswer"] as! Int
if (rightAnswer == 4){
displayAnswerChoice.text = "Correct"
}
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
}
Just assign the received documentdata to the property documentdata
if let documentdata = document?.data() {
self.documentdata = documentdata
self.questionLabel.text = documentdata["Question"] as? String
self.answerButtonOne.setTitle(documentdata["Answer1"] as? String, for:.normal)
self.answerButtonTwo.setTitle(documentdata["Answer2"] as? String, for:.normal)
self.answerButtonThree.setTitle(documentdata["Answer3"] as? String, for:.normal)
self.answerButtonFour.setTitle(documentdata["Answer4"] as? String, for:.normal)
}

Core Data insert

I try to learn Core Data and after many hours and a lot of tutorials, I am still confused. All the tutorials seem so complicated with so many elements involved. It would be very helpful if someone could give me an example of the most simple insert possible. (please without tables, navigation controllers... just insert a name and password)
I have created an entity of users with the attribute name and password
I have two textfields: name and password. I have the connection from the storyboard to the ViewController
I have a button
How can I save names and passwords when the user clicks to button?
#IBOutlet weak var name: UITextField!
#IBOutlet weak var password: UITextField!
#IBAction func button(_ sender: UIButton) {
}
First, do you have an NSManagedObjectContext available at this point? Assuming you do and it's called context
import UIKit
import CoreData
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if let viewController = window?.rootViewController as? ViewController {
viewController.context = persistentContainer.viewContext
}
return true
}
// ... other functions
}
import CoreData
class ViewController: UIViewController {
#IBOutlet weak var name: UITextField!
#IBOutlet weak var password: UITextField!
var context: NSManagedObjectContext!
override func viewDidLoad() {
super.viewDidLoad()
assert(context != nil)
}
#IBAction func button(_ sender: UIButton) {
guard name.hasText || password.hasText else { return }
let newUser = User(context: context)
if let nameString = name.text {
newUser.name = nameString
}
if let passwordString = password.text {
newUser.password = passwordString
}
context.insert(newUser)
saveContext()
}
func saveContext() {
if context.hasChanges {
do {
try context.save()
} catch {
print(error.localizedDescription)
}
}
}
}
Very simple example.
Instantiate the context lazily in the view controller
lazy var context : NSManagedObjectContext = {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
return appDelegate.persistentContainer.viewContext
}()
If it's going to be used only the in IBAction instantiate it temporarily in there (see commented out code)
Then in the IBAction write
#IBAction func button(_ sender: UIButton) {
guard name.hasText, !name.text!.first!.isWhitespace,
password.hasText, !password.text!.first!.isWhitespace else {
// show an alert that both text fields must not be empty and must not start with a whitespace characters.
return
}
// let appDelegate = UIApplication.shared.delegate as! AppDelegate
// let context = appDelegate.persistentContainer.viewContext
let user = User(context: context)
user.name = self.name.text!
user.password = self.password.text!
do {
try context.save()
} catch {
print(error)
}
}
Side note: To avoid ambiguity name the text fields more distinct for example
#IBOutlet weak var nameField: UITextField!
#IBOutlet weak var passwordField: UITextField!

Swift: Retrieve data from Firebase and display in table view

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")
}
}
From what you have shown the culprit is the postId, you are using it to fetch data from Firebase and yet you haven't shown anywhere what its value is. When the user taps on an image, the postId is not transfered to the SiteViewController.
In the SiteViewController remove the ! and replace it with ?, put an initializer that will take the postID as a parameter.
var postId:String?
func initPost(forImage postId: String) {
self.postId=postId
}
In the previous news feed VC inside the segue or didSelectForRow(i don't know what you use for transition, initialize the SiteViewController, so when it is presented it knows which ID to retrieve data for.
Another thing that needs mentioning is that you are using observe but you are not removing the observers.
EDIT: this answer was based on me not knowing what your HomeVC looked like.
if segue.identifier == "SiteSegue" {
let siteVC = segue.destination as! SiteViewController
let postId = sender as! String
siteVC.postId = postId
}