Issue fetching snapshot from Firebase for a Custom Cell using Swift 2

Question!

I defined a custom cell layout as shown below: enter image description here

I then added the desired values to my Firebase database as shown below: enter image description here

However, after modifying the code to get the desired values from the firebase database I am getting an exception. When I run it in debug I see that it is just skipping over the first line in the code below, therefore the array is empty and hence it throws the exception. I am still very new to Firebase and Swift. I am following this example http://www.appcoda.com/firebase/ to get my own results and I am now stuck at this issue. I'll appreciate any help. I am providing all of the code below.

//Populate array
        ServiceHistoryFBService.firebaseDBService.SERVICE_HISTORY_FOR_CURRENT_USER_REF.observeEventType(.Value, withBlock: { snapshot in

            // The snapshot is a current look at our jokes data.

            print(snapshot.value)

            self.orderHistoryArray = []

            if let snapshots = snapshot.children.allObjects as? [FDataSnapshot] {

                for snap in snapshots {

                    // Make our jokes array for the tableView.

                    if let postDictionary = snap.value as? Dictionary<String, AnyObject> {
                        let key = snap.key
                        let serviceOrder = ServiceOrder(key: key, dictionary: postDictionary)

                        // Items are returned chronologically, but it's more fun with the newest jokes first.

                        self.orderHistoryArray.insert(serviceOrder, atIndex: 0)
                    }
                }

            }

            // Be sure that the tableView updates when there is new data.

            self.tableView.reloadData()
        })

I defined the Custom Cell as follows:

import UIKit

class SummaryCustomTableViewCell: UITableViewCell {

    @IBOutlet weak var serviceOrderSummaryLabel: UILabel!
    @IBOutlet weak var dateLabel: UILabel!
    @IBOutlet weak var date: UILabel!
    @IBOutlet weak var label1: UILabel!
    @IBOutlet weak var label2: UILabel!
    @IBOutlet weak var label3: UILabel!
    @IBOutlet weak var label4: UILabel!
    @IBOutlet weak var label5: UILabel!
    @IBOutlet weak var label6: UILabel!
    @IBOutlet weak var label7: UILabel!
    @IBOutlet weak var label8: UILabel!
    @IBOutlet weak var label9: UILabel!
    @IBOutlet weak var label10: UILabel!
    @IBOutlet weak var label11: UILabel!
    @IBOutlet weak var label12: UILabel!
    @IBOutlet weak var label13: UILabel!
    @IBOutlet weak var label14: UILabel!
    @IBOutlet weak var more: UILabel!



    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

}

In my ViewController I am getting the snapshot from the Firebase database as follows by referencing these example: http://www.appcoda.com/firebase/

import UIKit
import Firebase

class ServiceHistoryTableViewController: UITableViewController {

    //Vars
    var orderHistoryArray = [ServiceOrder]()

    override func viewDidLoad() {
        super.viewDidLoad()

        //Populate array
        ServiceHistoryFBService.firebaseDBService.SERVICE_HISTORY_FOR_CURRENT_USER_REF.observeEventType(.Value, withBlock: { snapshot in

            // The snapshot is a current look at our jokes data.

            print(snapshot.value)

            self.orderHistoryArray = []

            if let snapshots = snapshot.children.allObjects as? [FDataSnapshot] {

                for snap in snapshots {

                    // Make our jokes array for the tableView.

                    if let postDictionary = snap.value as? Dictionary<String, AnyObject> {
                        let key = snap.key
                        let serviceOrder = ServiceOrder(key: key, dictionary: postDictionary)

                        // Items are returned chronologically, but it's more fun with the newest jokes first.

                        self.orderHistoryArray.insert(serviceOrder, atIndex: 0)
                    }
                }

            }

            // Be sure that the tableView updates when there is new data.

            self.tableView.reloadData()
        })
    }

    // MARK: - Table view data source

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            //return orderHistoryArray.count
        return 1
    }


    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("customSummaryCell", forIndexPath: indexPath) as! SummaryCustomTableViewCell

        cell.serviceOrderSummaryLabel.text = "SERVICE ORDER SUMMARY"
        cell.dateLabel.text = "Created:"

        if (orderHistoryArray[1].createdTimestamp.isEmpty) {
            cell.date.text = "Not selected"
        } else {
            cell.date.text = orderHistoryArray[0].createdTimestamp
        }
        if (orderHistoryArray[1].groceriesPickup.isEmpty) {
            cell.date.text = "Not selected"
        } else {
            cell.date.text = "Groceries Pickup"
        }
        if (orderHistoryArray[2].laundryDropoff.isEmpty) {
            cell.date.text = "Not selected"
        } else {
            cell.label1.text = "Laundry Dropoff"
        }
        if (orderHistoryArray[3].laundryPickup.isEmpty) {
            cell.date.text = "Not selected"
        } else {
            cell.label1.text = "Laundry Pickup"
        }
        if (orderHistoryArray[4].mealDelivery.isEmpty) {
            cell.date.text = "Not selected"
        } else {
            cell.label1.text = "Meal Delivery"
        }
        if (orderHistoryArray[5].petSiting.isEmpty) {
            cell.date.text = "Not selected"
        } else {
            cell.label1.text = "Pet Siting"
        }
        if (orderHistoryArray[6].petBathing.isEmpty) {
            cell.date.text = "Not selected"
        } else {
            cell.label1.text = "Pet Bathing"
        }
        if (orderHistoryArray[7].petFeeding.isEmpty) {
            cell.date.text = "Not selected"
        } else {
            cell.label1.text = "Pet Feeding"
        }
        if (orderHistoryArray[8].petWalking.isEmpty) {
            cell.date.text = "Not selected"
        } else {
            cell.label1.text = "Pet Walking"
        }
        if (orderHistoryArray[9].carpetCleaning.isEmpty) {
            cell.date.text = "Not selected"
        } else {
            cell.label1.text = "Carpet Cleaning"
        }
        if (orderHistoryArray[10].windowCleaning.isEmpty) {
            cell.date.text = "Not selected"
        } else {
            cell.label1.text = "Window Cleaning"
        }
        if (orderHistoryArray[11].carCleaning.isEmpty) {
            cell.date.text = "Not selected"
        } else {
            cell.label1.text = "Car Cleaning"
        }
        if (orderHistoryArray[12].yardCleaning.isEmpty) {
            cell.date.text = "Not selected"
        } else {
            cell.label1.text = "Yard Cleaning"
        }
        if (orderHistoryArray[13].lawnMowing.isEmpty) {
            cell.date.text = "Not selected"
        } else {
            cell.label1.text = "Lawn Mowing"
        }
        if (orderHistoryArray[14].courierServicing.isEmpty) {
            cell.date.text = "Not selected"
        } else {
            cell.label1.text = "Courier Servicing"
        }
        cell.more.text = "More..."

        return cell

    }

}

Below is the code for the ServiceHistoryFBService file which is referenced in the ViewController

import Foundation
import Firebase

class ServiceHistoryFBService {
    static let firebaseDBService = ServiceHistoryFBService()

    private var _BASE_REF = Firebase(url: "\(BASE_URL)")
    private var _SERVICE_HISTORY_FOR_CURRENT_USER_REF = Firebase(url: "\(BASE_URL)/service_history/uid")

    var BASE_REF: Firebase {
        return _BASE_REF
    }

    var SERVICE_HISTORY_FOR_CURRENT_USER_REF: Firebase {
        return _SERVICE_HISTORY_FOR_CURRENT_USER_REF
    }
}

Lastly, below is the code for the ServiceOrder file which is also referenced in the ViewController

import Foundation
import Firebase


class ServiceOrder: NSObject {

    //Autogenerated Firebase ID (Order No.)
    var key: String

    //Service Order/Request Creation Timestamp
    var createdTimestamp: String

    var groceriesPickup: String
    var laundryDropoff: String
    var laundryPickup: String
    var mealDelivery: String
    var petSiting: String
    var petBathing: String
    var petFeeding: String
    var petWalking: String
    var carpetCleaning: String
    var windowCleaning: String
    var carCleaning: String
    var yardCleaning: String
    var lawnMowing: String
    var courierServicing: String

    override init() {
        self.key = ""
        //Service Order Creation Timestamp
        self.createdTimestamp = ""
        self.groceriesPickup = "N"
        self.laundryDropoff = "N"
        self.laundryPickup = "N"
        self.mealDelivery = "N"
        self.petSiting = "N"
        self.petBathing = "N"
        self.petFeeding = "N"
        self.petWalking = "N"
        self.carpetCleaning = "N"
        self.windowCleaning = "N"
        self.carCleaning = "N"
        self.yardCleaning = "N"
        self.lawnMowing = "N"
        self.courierServicing = "N"
    }

    init(key: String, createdTimestamp: String,
                        groceriesPickup: String,
                        laundryDropoff: String,
                        laundryPickup: String,
                        mealDelivery: String,
                        petSiting: String,
                        petBathing: String,
                        petFeeding: String,
                        petWalking: String,
                        carpetCleaning: String,
                        windowCleaning: String,
                        carCleaning: String,
                        yardCleaning: String,
                        lawnMowing: String,
                        courierServicing: String) {
        self.key = key
        self.createdTimestamp = createdTimestamp
        self.groceriesPickup = groceriesPickup
        self.laundryDropoff = laundryDropoff
        self.laundryPickup = laundryPickup
        self.mealDelivery = mealDelivery
        self.petSiting = petSiting
        self.petBathing = petBathing
        self.petFeeding = petFeeding
        self.petWalking = petWalking
        self.carpetCleaning = carpetCleaning
        self.windowCleaning = windowCleaning
        self.carCleaning = carCleaning
        self.yardCleaning = yardCleaning
        self.lawnMowing = lawnMowing
        self.courierServicing = courierServicing
    }

    // Return a Dictionary<String, Bool> from ServiceOrder object
    init(key: String, dictionary: Dictionary<String, AnyObject>){
        self.key = key
        self.createdTimestamp = dictionary["createdTimestamp"] as! String
        self.groceriesPickup = dictionary["groceriesPickup"] as! String
        self.laundryDropoff = dictionary["laundryDropoff"] as! String
        self.laundryPickup = dictionary["laundryPickup"] as! String
        self.mealDelivery = dictionary["mealDelivery"] as! String
        self.petSiting = dictionary["petSiting"] as! String
        self.petBathing = dictionary["petBathing"] as! String
        self.petFeeding = dictionary["petFeeding"] as! String
        self.petWalking = dictionary["petWalking"] as! String
        self.carpetCleaning = dictionary["] carpetCleaning"] as! String
        self.windowCleaning = dictionary["windowCleaning"] as! String
        self.carCleaning = dictionary["carCleaning"] as! String
        self.yardCleaning = dictionary["yardCleaning"] as! String
        self.lawnMowing = dictionary["lawnMowing"] as! String
        self.courierServicing = dictionary["courierServicing"] as! String
    }


}
By : Maria1985


Answers

In your "ServiceHistoryFBService" file you have this line

private var _SERVICE_HISTORY_FOR_CURRENT_USER_REF = Firebase(url: "\(BASE_URL)/service_history/uid")

With this Firebase reference you are looking for the path "/sample_project/service_history/uid", which value is NSNull because you are hardcoding an extra "uid" child at the end, your path should be "/sample_project/service_history". If you want to access the service_history of the currently logged in user you can do something like this:

If you are using the Firebase Legacy Console

if let authData = ServiceHistoryFBService.firebaseDBService._REF_BASE.authData{
    ServiceHistoryFBService.firebaseDBService.SERVICE_HISTORY_FOR_CURRENT_USER_REF.childByAppendingPath(authData.uid)
      .observeEventType //etc
}

If you are using the new Firebase Console released at Google I/O 2016 is almost the same but you need to get the user like this:

if let user = FIRAuth.auth()?.currentUser {
  ServiceHistoryFBService.firebaseDBService.SERVICE_HISTORY_FOR_CURRENT_USER_REF.child(user.uid)
      .observeEventType //etc
}
By : Ymmanuel


This video can help you solving your question :)
By: admin