Firebase iOS Swift 致命错误:NSArray 元素无法匹配 Swift Array 元素类型

Posted

技术标签:

【中文标题】Firebase iOS Swift 致命错误:NSArray 元素无法匹配 Swift Array 元素类型【英文标题】:Firebase iOS Swift fatal error: NSArray element failed to match the Swift Array Element type 【发布时间】: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 数组 时发生。但是,数组计数似乎一直都是正确的。

【问题讨论】:

【参考方案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.flatMapBidder(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 便利初始化中添加一个调试点。我猜它的失败是因为警卫条件。可能有一些不匹配或拼写错误

以上是关于Firebase iOS Swift 致命错误:NSArray 元素无法匹配 Swift Array 元素类型的主要内容,如果未能解决你的问题,请参考以下文章

致命错误:索引超出范围 - Swift 3 和 Firebase

使用 Firebase 进行 iOS 开发时如何修复致命错误?

颤振:致命错误:找不到模块“firebase_analytics”

使用 Firebase ios 获取数据

致命错误:找不到模块“firebase_core”

(iOS Swift) 从 Core Data 获取记录返回致命错误或 nil