bibscy
bibscy

Reputation: 2708

Could not cast value of type '__NSDictionaryM' (0x1111152b0) to 'FIRDataSnapshot' Firebase Swift 3

I am trying to read nested data structures from Firebase Database, but I don't know how to manage the case when an object of type [String:AnyObject] could be nil.
When readFeesCleaner(callback_) is called, it throws an error.

  func readFeesCleaner(callback: @escaping ((_ feesCleaner: FeesCleaner) -> Void)) {

 dbRef.child("FeesCleaner").child(self.uidOfTextField!).observeSingleEvent(of: .value, with: { (snapshot: FIRDataSnapshot) in

        guard !(snapshot.value is NSNull) else {
            return
        }

       //throws error: signal SIGABRTCould not cast value of type '__NSDictionaryM' (0x1111152b0) to 'FIRDataSnapshot' (0x10ef16d18).
            let feesCleanersReceived = FeesCleaner(snapshot: (snapshot.value)! as! FIRDataSnapshot)
                callback(feesCleanersReceived)

    }) { (error:Error) in
        print(#line, "\(error.localizedDescription)")
    }
 } 


struct FeesCleaner {

   var outstandingFees: AnyObject!
   var timeStampFeesSaved: [String:AnyObject]!
   var backgroundCheck: AnyObject!

    init(
       outstandingFees: AnyObject? = nil, //value might not exist when reading
       timeStampFeesSaved: [String:AnyObject]? = nil,// value might not exist when reading
       backgroundCheck: AnyObject) {

       self.outstandingFees = outstandingFees
       self.timeStampFeesSaved = timeStampFeesSaved
       self.backgroundCheck = backgroundCheck   
  }//end of init

    //read data here
     [full struct data here][1]
      https://gist.github.com/bibscy/dc48f7107459379e045a50fdbbc35335


}//end of struct

Upvotes: 0

Views: 257

Answers (1)

Jay
Jay

Reputation: 35648

There's a number of issues here. First:

how to manage the case when an object of type [String:AnyObject] could be nil.

You've handled that with the prior statement, noting that you can also add

if snapshot.exists == false {return}

Second: You've got to handle optionals properly - if a var could be nil, you need code in place to handle that situation and not plow through it. If you force unwrap an optional you are essentially stating that for sure, it will never be nil, so basically, don't do that.

One fix could be to simply pass the snapshot as a DataSnapshot and then pull out the properties one at a time; if they exist, assign them, if not set to 0 or nil or some other placeholder.

Something like this inside the Firebase closure:

let feesCleanersReceived = FeesCleaner(withSnapshot: snapshot)

and then your struct like this: note we are leveraging the nil coalescing operator, ??

struct FeesCleanerStruct {
    var outstandingFees: String?
    var timeStampFeesSaved: String?

    init(withSnapshot: DataSnapshot) {
        let dict = withSnapshot.value as! [String: Any]
        self.outstandingFees = dict["outstandingFees"] as? String ?? "0.0"
        self.timeStampFeesSaved = dict["timeStampFeesSaved"] as? String ?? "0"
    }
}

Upvotes: 1

Related Questions