1

I am trying to integrate Firebase to my app and want to store data in the below format.

"chits": {
"Chit-1": {
  "Bidders": [
    {
      "bankAccNumber": "5555566966",
      "bankIFSC": "GFHJJHHJ",
      "bankName": "55666",
      "bidderEmail": "desi@venkat.co.in",
      "bidderId": "Bidder-1",
      "bidderName": "Venkat Desi",
      "bidderPhone": "9999999999",
      "checked": false,
      "paymentType": 66555
    },
    {
      "bankAccNumber": "5555566966",
      "bankIFSC": "GFHJJHHJ",
      "bankName": "55666",
      "bidderEmail": "desi@venkat.co.in",
      "bidderId": "Bidder-2",
      "bidderName": "Venkat Desi",
      "bidderPhone": "9999999999",
      "checked": false,
      "paymentType": 66555
    },
    {
      "bankAccNumber": "5555566966",
      "bankIFSC": "GFHJJHHJ",
      "bankName": "55666",
      "bidderEmail": "desi@venkat.co.in",
      "bidderId": "Bidder-3",
      "bidderName": "Venkat Desi",
      "bidderPhone": "9999999999",
      "checked": false,
      "paymentType": 66555
    }
  ],
  "chitId": "Chit-1",
  "chitName": "ABC1",
  "chitTotalValue": 240000,
  "endDate": "11/10/2018",
  "monthlyShare": 1000,
  "startDate": "11/10/2017",
  "totalMonths": 12
},
"Chit-2": {
  "bidderIds": [
    {
      "bidderId": "0",
      "bidderName": "Rajesh Challuri",
      "bidderPhone": "3333333333",
      "checked": true,
      "paymentType": 0
    },
    {
      "bidderId": "0",
      "bidderName": "Govinda Bhonsle",
      "bidderPhone": "9999999999",
      "checked": true,
      "paymentType": 0
    }
  ],
  "chitId": "Chit-2",
  "chitName": "ABC2",
  "chitTotalValue": 100000,
  "endDate": "12/10/2018",
  "monthlyShare": 8000,
  "startDate": "12/10/2017",
  "totalMonths": 12
},
"Chit-3": {
  "bidderIds": [
    {
      "bidderId": "0",
      "bidderName": "Rajesh Challuri",
      "bidderPhone": "3333333333",
      "checked": true,
      "paymentType": 0
    },
    {
      "bidderId": "0",
      "bidderName": "Govinda Bhonsle",
      "bidderPhone": "9999999999",
      "checked": true,
      "paymentType": 0
    }
  ],
  "chitId": "Chit-3",
  "chitName": "ABC3",
  "chitTotalValue": 200000,
  "endDate": "13/10/2018",
  "monthlyShare": 2000,
  "startDate": "13/10/2017",
  "totalMonths": 12
}}}

I am successfully able to store Bidder data which is name,email,phone, account details etc. However, i also need to store Chit data as well. Below is the code for both the classes.

Bidder.swift

class Bidder {

let bidderId: Int
let bidderName: String
let bidderEmail: String
let bidderPhone : String
let modeOfPayment: Int
let bidderBankName: String
let bidderBankAcno: String
let bidderIfscCode: String
let paymentArray :  [[String:String]]?
let chitrefArray : [String]?
let ref: FIRDatabaseReference?

init(bidderId: Int, bidderName: String,bidderEmail: String, bidderPhone: String, modeOfPayment: Int, bidderBankName: String, bidderBankAcno: String, bidderIfscCode: String,paymentArray:  [[String:String]], chitrefArray: [String]) {
    self.bidderId = bidderId
    self.bidderName = bidderName
    self.bidderEmail = bidderEmail
    self.bidderPhone = bidderPhone
    self.modeOfPayment = modeOfPayment
    self.bidderBankName = bidderBankName
    self.bidderBankAcno = bidderBankAcno
    self.bidderIfscCode = bidderIfscCode
    self.paymentArray = paymentArray
    self.chitrefArray = chitrefArray
    self.ref = nil
}

init(snapshot: FIRDataSnapshot) {
    let snapshotValue = snapshot.value as! [String: AnyObject]
    bidderId = snapshotValue["bidderId"] as! Int
    bidderName = snapshotValue["bidderName"] as! String
    bidderEmail = snapshotValue["bidderEmail"] as! String
    bidderPhone = snapshotValue["bidderPhone"] as! String
    modeOfPayment = snapshotValue["modeOfPayment"] as! Int
    bidderBankName = snapshotValue["bidderBankName"] as! String
    bidderBankAcno = snapshotValue["bidderBankAcno"] as! String
    bidderIfscCode = snapshotValue["bidderIfscCode"] as! String
    paymentArray = snapshotValue["paymentArray"] as? [[String:String]]
    chitrefArray = snapshotValue["chitrefArray"] as? [String]
    ref = snapshot.ref
}

func toAnyObject() -> Any {
    return [
        "bidderId" : bidderId,
        "bidderName" : bidderName,
        "bidderEmail": bidderEmail,
        "bidderPhone": bidderPhone,
        "modeOfPayment": modeOfPayment,
        "bidderBankName":bidderBankName,
        "bidderBankAcno": bidderBankAcno,
        "bidderIfscCode":bidderIfscCode,
        "paymentArray": paymentArray!,
        "chitrefArray" : chitrefArray!
    ]
}}

Chit.swift

struct ChitObject {

var chitId : Int
var chitName: String
var startDate: String
var endDate : String
var chitTotalAmt: Int
var chitTotalMonths: Int
var bidders: [Bidder]
var ref: FIRDatabaseReference?

init(chitId: Int,chitName: String, startDate: String, endDate: String, chitTotalAmt: Int, chitTotalMonths: Int, bidders: [Bidder]) {
    self.chitId = chitId
    self.chitName = chitName
    self.startDate = startDate
    self.endDate = endDate
    self.chitTotalAmt = chitTotalAmt
    self.chitTotalMonths = chitTotalMonths
    self.bidders = bidders 
    self.ref = nil
}

init(snapshot: FIRDataSnapshot) {
    let snapshotValue = snapshot.value as! [String: Any]
    chitId = snapshotValue["chitId"] as! Int
    chitName = snapshotValue["chitName"] as! String
    startDate = snapshotValue["startDate"] as! String
    endDate = snapshotValue["endDate"] as! String
    chitTotalAmt = snapshotValue["chitTotalAmt"] as! Int
    chitTotalMonths = snapshotValue["chitTotalMonths"] as! Int
    bidders = snapshotValue["bidders"] as! [Bidder]
    ref = snapshot.ref
}

func toAnyObject() -> Dictionary<String, Any>
{
    return [
        "chitId" : chitId,
        "chitName": chitName,
        "startDate": startDate,
        "endDate": endDate,
        "chitTotalAmt":chitTotalAmt,
        "chitTotalMonths": chitTotalMonths,
        "bidders":bidders
    ] 
}}

ViewController.swift

let chitItem = ChitObject(chitId: self.chitId, chitName: chitName.text!, startDate: startDate.text!, endDate: endDate.text!, chitTotalAmt: Int(totalAmount.text!)!, chitTotalMonths:
            Int(totalMonths.text!)!, bidders: biddersArray)
        let chitItemRef = ChitUtils.chitRef.child((chitName.text?.lowercased())!) // Crashes here at this point. 
        chitItemRef.setValue(chitItem.toAnyObject(), withCompletionBlock: { erorr , dataRef in
            if erorr != nil
            {
                let _ = self.navigationController?.popViewController(animated: true)
            }
        })
        chitItemRef.setValue(chitItem.toAnyObject())

Output : *** Terminating app due to uncaught exception 'InvalidFirebaseData', reason: '(setValue:withCompletionBlock:) Cannot store object of type _SwiftValue at bidders.0. Can only store objects of type NSNumber, NSString, NSDictionary, and NSArray.'

govind kumar
  • 205
  • 4
  • 12
  • 1
    I think that this line is causing the issue: `"bidders":bidders` in `toAnyObject()` of `Chit.swift`, try `"bidders":bidders.map({$0. toAnyObject()})` or something like that. – Larme Oct 11 '17 at 10:09
  • @Larme Thanks a ton. It works beautifully – govind kumar Oct 11 '17 at 10:17
  • @Larme - I am facing this issue when trying to print the data of Bidders an array of type **Bidder** class. Error **NSArray element failed to match the Swift Array Element type** – govind kumar Oct 12 '17 at 10:24
  • https://stackoverflow.com/questions/25484554/fatal-error-nsarray-element-failed-to-match-the-swift-array-element-type ? Where do you print it? Where is your issue exactly? – Larme Oct 12 '17 at 11:54
  • @Larme - It crashes when i am trying to **print(self.chitsArray[0].bidders)** I think it's because of the above code **"bidders":bidders.map({$0. toAnyObject()})** not sure exactly. – govind kumar Oct 12 '17 at 11:58
  • How is declared `self.chitsArray`? Do you have the issue once you created the `Chit` object to put into `self.chitsArray` by doing `print(myChitObject.bidders)`? If yes, could it be because of `bidders = snapshotValue["bidders"] as! [Bidder]`? That's not an array of `Bidders` objects? Also, it seems to be another question. So I'd open a new one if I were you. – Larme Oct 12 '17 at 12:01
  • declaration `var chitsArray = [ChitObject]()` and the data `ChitUtils.chitRef.queryOrdered(byChild: "chitId").observe(.value, with: { snapshot in if snapshot.childrenCount > 0 { for item in snapshot.children { let chitItem = ChitObject(snapshot: item as! FIRDataSnapshot) print(chitItem.bidders)}}}` It crashes at the _print_ statement – govind kumar Oct 12 '17 at 12:12
  • And `print(chitItem.bidders)` works? – Larme Oct 12 '17 at 12:14
  • @Larme No shows `fatal error: NSArray element failed to match the Swift Array Element type` – govind kumar Oct 12 '17 at 12:15
  • @Larme - As you said, I have posted a new question [link](https://stackoverflow.com/questions/46728470/firebase-ios-swift-fatal-error-nsarray-element-failed-to-match-the-swift-array) I am unable to trace the issue. – govind kumar Oct 15 '17 at 10:14

1 Answers1

1

You are trying to set an array of Bidder objects in firebase:

In your ChitObject:

var bidders: [Bidder]

toAnyObject() method:

"bidders":bidders

Firebase will not know what this is and is expecting NSNumber, NSString, NSDictionary, or NSArray. as per the error message. (It is an Array of your own custom objects).

Try mapping your array of bidders into an array of bidders.toAnyClass() so that they all use the Firebase primitive types.

  • I am facing this issue when trying to print the data of Bidders an array of type **Bidder** class. Error **NSArray element failed to match the Swift Array Element type** – govind kumar Oct 12 '17 at 11:37