I get the error listed below when I try to save a nested model in Firebase. It is because the data model is not properly formatted, but I have searched for hours and I am stuck now.

Cannot store object of type _SwiftValue at . Can only store objects of type NSNumber, NSString, NSDictionary, and NSArray.

The model I want to write looks like this:

payPeriodDateStartDate
payPeriodEndDate
  -bookings 
     booking1
          hours: 
          originalPriceOfBooking:
          cancelledBy   // <- optional, it may or may not exist
             -timeStamp // <- a timeStamp node
                cleanerUID:
                costToCancelByCleaner:

     booking2 

I think that I am not properly converting cancelledBy in this code snippet.

       for booking in self.bookingsFromQuery { 
          let bookingForPayPeriod = DisbursePaymentData(
           numberOfHours: booking.NumberOfHours
            cancelledBy: booking.objectsUnderCancelledBy) // <- this argument is not properly converted to AnyObject and causes exception 'InvalidFirebaseData
        )

Below you can find the full code.

 //FireBaseData is used to read from Firebase
struct FireBaseData {

  var BookingNumber:String!
  var PostCode:String!
  var objectsUnderCancelledBy:[String: CancelledObject]! //the object that is causing the crash of the app, it is optional, cleaner may/may not cancel booking

    init(snapshot:FIRDataSnapshot){
    //I am initializing just the property we are concerned about, in my project all properties are initialized 

    //CancelledBy is nested
  if ((snapshot.value! as? NSDictionary)?["BookingNumber"] as? String) != nil {    
        var cancelledItems = [String: CancelledObject]()

        //each key:value under the bookingNumber
        for item in snapshot.children{
          let elementUnderBookingNumber = item as! FIRDataSnapshot
            if elementUnderBookingNumber.key == "CancelledBy" {

                //iterate through the elements under each timeStamp
                for objectUnderTimeStamp in elementUnderBookingNumber.children {
                    let item = CancelledObject(snapshot: objectUnderTimeStamp as! FIRDataSnapshot)
                    //assign the timeStamp as a key for retrieved item
                    cancelledItems["\(item.key!)"] = item
                }
            }
        }
          self.objectsUnderCancelledBy = cancelledItems
   }//end of init
}//end of struct FirebaseData



  //holds data under CancelledBy key when data is read from Firebase 
 class CancelledObject {

     var cleanerUID: String!
     var costToCancelByCleaner: String!
    init() {
           if let cleanerUIDContent = (snapshot.value! as? NSDictionary)?["CleanerUID"] as? String {
         self.cleanerUID = cleanerUIDContent
       }
    }
 }//end of CancelledObject


     //DisbursePaymentData is used to update the database
     struct DisbursePaymentData {

     var payPeriodDateStartDate:String!
     var payPeriodEndDate:String!
     //- optional, cancelledBy might not exist in Database
     var cancelledBy: [String: CancelledObject]! 
     var numberOfHours:String!
       init(
    payPeriodDateStartDate:String,
    payPeriodEndDate:String) {
       self.payPeriodDateStartDate = payPeriodDateStartDate
       self.payPeriodEndDate = payPeriodEndDate
     }

    init(
      numberOfHours:String,
      cancelledBy: [String:CancelledObject]!
     ) {
        self.numberOfHours = numberOfHours
        self.cancelledBy =  cancelledBy
     } 


   //enables to convert the values to AnyObject
func convertDisbursePaymentDataToAnyObject() -> AnyObject {
    var someDict = [String : AnyObject]()

    someDict["numberOfHours"] = self.numberOfHours as AnyObject?
    someDict["cancelledBy"] = self.cancelledBy as AnyObject? //<- is this the way to convert cancelledBy to AnyObject?
    return someDict as AnyObject
}


}//end of struct DisbursePaymentData





  class UpdateFirebase {

      var bookingsFromQuery = [FireBaseData]()

       override func viewDidLoad() {
         super.viewDidLoad()
        //data was successfully read from Firebase

       var finalBookingArray = [String: AnyObject]()

      for booking in self.bookingsFromQuery { 
          let bookingForPayPeriod = DisbursePaymentData(

           numberOfHours: booking.NumberOfHours
          cancelledBy: booking.objectsUnderCancelledBy) // <- this argument is not properly converted to AnyObject and causes exception 'InvalidFirebaseData
        )
           //convert each booking to AnyObject
          let bookingCompleted = bookingForPayPeriod.convertDisbursePaymentDataToAnyObject()
   //assign to BookingNumber of each loop the converted object
         finalBookingArray[booking.BookingNumber] = bookingCompleted
    }//end of for loop

     let finalObject = DisbursePaymentData(
            payPeriodDateStartDate: self.fromDateString.text!,
            payPeriodEndDate: self.toDateString.text!)

      let childUpdates = ["Payments/\(uid)/\(timeStamp)/\(paymentRef)" : finalObject,
                          "Payments/\(uid)/\(timeStamp)/\(paymentRef)/\("bookings")" : finalBookingArray] as [String : Any] 

       self.dbRef.updateChildValues(childUpdates)
   }//end of viewDidLoad
 }
0

There are 0 answers