Firebase检索数据 - 无法转换值

Ant*_*ine 5 json ios firebase swift firebase-realtime-database

首先,我检查了这些对我没有帮助的答案: Swift JSON错误,无法将'__NSArrayM'(0x507b58)类型的值转换为'NSDictionary'(0x507d74)

从Firebase获取数据

从Firebase(3.x)检索数据时,出现错误,即:

Could not cast value of type '__NSArrayM' (0x10ca9fc30) to 'NSDictionary' (0x10caa0108).
Run Code Online (Sandbox Code Playgroud)

使用此代码和树:

树:

在此输入图像描述

检索功能:

func retrievePlanes() {

    print("Retrieve Planes")

    ref = FIRDatabase.database().reference(withPath: "results")

    ref.observe(.value, with: { snapshot in

        var newItems: [Planes] = []

        for item in snapshot.children {
            let planesItem = Planes(snapshot: item as! FIRDataSnapshot)
            newItems.append(planesItem)
        }

        self.planes = newItems
        self.tableView.reloadData()

    })

}
Run Code Online (Sandbox Code Playgroud)

Planes.swift - 管理数据

import Foundation
import Firebase
import FirebaseDatabase

struct Planes {

    let key: String!
    let name: String!
    let code:String!
    let flightRange: Int?
    let typicalSeats: Int?
    let maxSeats: Int?
    let wingSpan: String!
    let takeoffLength: Int?
    let rateClimb: Int?
    let maxCruiseAltitude: Int?
    let cruiseSpeed: String!
    let landingLength: Int?
    let engines: String!
    let votes: Int?
    let data: String!
    let imagePlane:String!
    let imageTakenFrom: String!
    let ref: FIRDatabaseReference?

    init(name: String, code: String, flightRange: Int, typicalSeats: Int, maxSeats: Int, wingSpan: String, takeoffLength: Int, rateClimb: Int, maxCruiseAltitude: Int, cruiseSpeed: String, landingLength: Int, engines: String, votes: Int, data: String, imagePlane: String, imageTakenFrom: String, key: String = "") {

        self.key = key
        self.name = name
        self.code = code
        self.flightRange = flightRange
        self.typicalSeats = typicalSeats
        self.maxSeats = maxSeats
        self.wingSpan = wingSpan
        self.takeoffLength = takeoffLength
        self.rateClimb = rateClimb
        self.maxCruiseAltitude = maxCruiseAltitude
        self.cruiseSpeed = cruiseSpeed
        self.landingLength = landingLength
        self.engines = engines
        self.votes = votes
        self.data = data
        self.imagePlane = imagePlane
        self.imageTakenFrom = imageTakenFrom
        self.ref = nil

    }

    init(snapshot: FIRDataSnapshot) {

        ref = snapshot.ref
        key = snapshot.key
        let snapshotValue = snapshot.value as! [String:AnyObject]
        name = snapshotValue["name"] as! String
        code = snapshotValue["code"] as! String
        flightRange = snapshotValue["intFlightRange"] as? Int
        typicalSeats = snapshotValue["intTypicalSeats"] as? Int
        maxSeats = snapshotValue["intMaxSeats"] as? Int
        wingSpan = snapshotValue["wingSpan"] as! String
        takeoffLength = snapshotValue["intTakeoffLength"] as? Int
        rateClimb = snapshotValue["intRateClimb"] as? Int
        maxCruiseAltitude = snapshotValue["intMaxCruiseAltitude"] as? Int
        cruiseSpeed = snapshotValue["cruiseSpeed"] as! String
        landingLength = snapshotValue["intLandingLength"] as? Int
        engines = snapshotValue["engines"] as! String
        votes = snapshotValue["votes"] as? Int
        data = snapshotValue["data"] as! String
        imagePlane = snapshotValue["planeImage"] as! String
        imageTakenFrom = snapshotValue["imageTakenFrom"] as! String
    }
Run Code Online (Sandbox Code Playgroud)

在线上 : let snapshotValue = snapshot.value as! [String:AnyObject]

我想这是由于下面[String:AnyObject]因无法检索的快照值所致Int.(当我String在另一个案例中时,它正在工作).

我也知道Firebase将JSON树"转换"为这些对象[link]:

  • NSString
  • NSNumber
  • NSArray
  • NSDictionnary

但我无法弄清楚snapshot.value行中需要更改的内容才能使其正常工作.

谢谢你的帮助.

编辑:我刚刚发送了一个疑难解答请求.将发布更新. 编辑2:看杰伊的答案.在我的情况下树是错的.

Jay*_*Jay 3

我拿了你的代码并将其缩小一点进行测试,它正在工作。(注意 OS X 和 Swift 3 上的 Firebase 2.x 但代码类似)

火力基地结构:

  "what-am" : {
    "results" : [ {
      "code" : "738/B738",
      "data" : "Boeing",
      "engines" : "Rolls"
    }, {
      "code" : "727/B727",
      "data" : "Boeing",
      "engines" : "Pratt"
    } ]
  }
Run Code Online (Sandbox Code Playgroud)

这是 Planes 结构

struct Planes {

    var code:String!
    var data: String!
    var engines: String!

    init(code: String, data: String, engines: String ) {

        self.code = code
        self.data = data
        self.engines = engines
    }

    init(snapshot: FDataSnapshot) {

        let snapshotValue = snapshot.value as! [String:AnyObject]

        code = snapshotValue["code"] as! String
        data = snapshotValue["data"] as! String
        engines = snapshotValue["engines"] as! String
    }
}
Run Code Online (Sandbox Code Playgroud)

然后是在两个平面中读取、填充和数组然后打印数组的代码。

let ref = self.myRootRef.child(byAppendingPath: "what-am/results")!

ref.observe(.value, with: { snapshot in

        if ( snapshot!.value is NSNull ) {
            print("not found")
        } else {

            var newItems: [Planes] = []

            for item in (snapshot?.children)! {
                let planesItem = Planes(snapshot: item as! FDataSnapshot)
                newItems.append(planesItem)
            }

            self.planes = newItems
            print(self.planes)

        }
})
Run Code Online (Sandbox Code Playgroud)

最后是输出

[Swift_Firebase_Test.Planes(code: 738/B738, data: Boeing, engines: Rolls),
 Swift_Firebase_Test.Planes(code: 727/B727, data: Boeing, engines: Pratt)]
Run Code Online (Sandbox Code Playgroud)

当我从 Planes 结构中删除时,键和名称为零。

您询问的线路

let snapshotValue = snapshot.value as! [String:AnyObject]
Run Code Online (Sandbox Code Playgroud)

有效,因为快照包含一系列键:值对,因此 String:AnyObject 可以工作。

此行因 Swift 3 而更改

for item in (snapshot?.children)!
Run Code Online (Sandbox Code Playgroud)

但除此之外,代码还可以工作。

尝试此操作以确保您正在读取正确的节点。这会读取上述结构并打印出每种引擎类型。(经过测试并有效)

 let ref = self.myRootRef.child(byAppendingPath: "what-am/results")!
 ref.observe(.value, with: { snapshot in
      if ( snapshot!.value is NSNull ) {
           print("not found")
      } else {
           for child in (snapshot?.children)! {
                let snap = child as! FDataSnapshot
                let dict = snap.value as! [String: String]
                let engines = dict["engines"]
                print(engines!)
           }    
      }
 })
Run Code Online (Sandbox Code Playgroud)