【问题标题】:Firebase iOS Swift fatal error: NSArray element failed to match the Swift Array Element typeFirebase iOS Swift 致命错误:NSArray 元素无法匹配 Swift Array 元素类型
【发布时间】:2017-10-13 11:05:45
【问题描述】:

我正在尝试从 firebase 数据库中获取数据,数据格式如下。

{
  "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
        }
      ],
      "chitId": "Chit-1",
      "chitName": "ABC1",
      "chitTotalValue": 240000,
      "endDate": "11/10/2018",
      "monthlyShare": 1000,
      "startDate": "11/10/2017",
      "totalMonths": 12
    }
  }
}

根据上面的JSON,我已经创建了模型

Bidder.swift

    class Bidder {

    var bidderId: Int
    var bidderName: String
    var bidderEmail: String
    var bidderPhone : String
    var modeOfPayment: Int
    var bidderBankName: String
    var bidderBankAcno: String
    var bidderIfscCode: String
    var paymentArray : [[String:String]]?
    var chitrefArray : [String]?
    var 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 as Any,
            "chitrefArray" : chitrefArray as Any
        ]
    }

}

ChitObject.swift

class 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: AnyObject]
        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.map({$0.toAnyObject()})
        ]
    }

}

但是,在 Viewcontroller 中,我试图从下面的代码中获取 biddersList

var chitsArray = [ChitObject]()
 ChitUtils.chitRef.queryOrdered(byChild: "chitId").observe(.value, with: { snapshot in
            if snapshot.childrenCount > 0
            {
                self.chitsArray.removeAll()
                for item in snapshot.children
                {
                    let chitItem = ChitObject(snapshot: item as! FIRDataSnapshot)
                    self.chitsArray.append(chitItem)
                }
                    self.chitsArray = self.chitsArray.reversed()
                    print(self.chitsArray.first!.bidders)
                    ChitUtils.lastChitId = (self.chitsArray.first?.chitId)! + 1
                    self.chitsTableView.reloadData()
            }
        })

致命错误仅在尝试访问 print(self.chitsArray.first!.bidders)bidders 数组 时发生。但是,数组计数似乎一直都是正确的。

【问题讨论】:

    标签: ios swift firebase swift3 firebase-realtime-database


    【解决方案1】:

    问题出在您的 ChitObject 课程中,特别是这里:

    bidders = snapshotValue["bidders"] as! [Bidder]
    

    您需要创建一个投标人数组并将其分配给投标人变量。遍历从 snapshotValue["bidders"] 获得的数组,并为每个值创建 Bidders 对象并将其分配到 Swift 数组中。

    我没有与 Firebase 合作过,但这样的事情可能会奏效:

    init(snapshot: FIRDataSnapshot) {
        let snapshotValue = snapshot.value as! [String: AnyObject]
        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
        if let biddersArray = snapshotValue["bidders"] as? [[String:Any]] {
            bidders = biddersArray.flatMap{Bidder(dict:$0)}
        }
        ref = snapshot.ref
    }
    

    已编辑:

    class Bidder {
    
        var bidderId: Int
        var bidderName: String
        var bidderEmail: String
        var bidderPhone : String
        var modeOfPayment: Int
        var bidderBankName: String
        var bidderBankAcno: String
        var bidderIfscCode: String
        var paymentArray : [[String:String]]?
        var chitrefArray : [String]?
        var ref: FIRDatabaseReference?
    
        convenience init?(dict:[String:Any]) {
            guard let bidderId = dict["bidderId"] as? Int, let bidderName = dict["bidderName"] as? String, let bidderEmail = dict["bidderEmail"] as? String, let bidderPhone = dict["bidderPhone"] as? String, let modeOfPayment = dict["paymentType"] as? Int, let bidderBankName = dict["bankName"] as? String, let bidderBankAcno = dict["bankAccNumber"] as? String, let bidderIfscCode = dict["bankIFSC"] as? String else {
                return nil
            }
            self.init(bidderId: bidderId, bidderName: bidderName, bidderEmail: bidderEmail, bidderPhone: bidderPhone, modeOfPayment: modeOfPayment, bidderBankName: bidderBankName, bidderBankAcno: bidderBankAcno, bidderIfscCode: bidderIfscCode, paymentArray: [[]], chitrefArray: [])
        }
    
        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 as Any,
                "chitrefArray" : chitrefArray as Any
            ]
        }
    
    }
    

    【讨论】:

    • 你的意思是说,我必须为每个项目分配每个变量?能不能发个例子,让我有个清晰的认识。
    • @govindkumar:编辑了答案。基本上你需要从 snapshotValue["bidders"] 中获取 Array 的值。我没有使用 Firebase,但可能是编辑作品。
    • If 条件总是失败导致一个空的biddersArray
    • 在调试时,您在 snapshotValue[“bidders”] 中获得的值类型是什么?
    • 在 Bidders 便利初始化中添加一个调试点。我猜它的失败是因为警卫条件。可能有一些不匹配或拼写错误
    猜你喜欢
    • 2014-10-18
    • 1970-01-01
    • 2014-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-27
    • 2015-01-28
    • 1970-01-01
    相关资源
    最近更新 更多