Firebase检索数据 – 无法投射价值

首先,我已经检查了这些不帮我的答案: Swift JSON错误,无法将types'__NSArrayM'(0x507b58)的值转换为'NSDictionary'(0x507d74)

从Firebase获取数据

从Firebase(3.x)检索数据时,发生的错误是:

Could not cast value of type '__NSArrayM' (0x10ca9fc30) to 'NSDictionary' (0x10caa0108). 

用这个代码和树:

树:

在这里输入图像说明

检索function:

 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() }) } 

Planes.swift – pipe理数据

 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 } 

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

我想这是由于下面的Int导致无法在[String:AnyObject]下检索的快照值。 (在另一种情况下,我只有String时正在工作)。

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

  • NSString
  • NSNumber
  • NSArray
  • NSDictionnary

但我无法弄清楚在snapshot.value行中必须改变什么才能使其工作。

谢谢你的帮助。

编辑:我刚刚发送了一个故障排除请求。 将张贴更新。 编辑2:看杰伊的答案。 在我的情况下,树是错的。

我把你的代码缩小了一点,用于testing,它正在工作。 (请注意OS X和Swift 3上的Firebase 2.x,但代码类似)

Firebase结构:

  "what-am" : { "results" : [ { "code" : "738/B738", "data" : "Boeing", "engines" : "Rolls" }, { "code" : "727/B727", "data" : "Boeing", "engines" : "Pratt" } ] } 

这是平面结构

 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 } } 

然后读取两个平面的代码,填充和数组,然后打印数组。

 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) } }) 

最后输出

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

键和名称是零,因为我从飞机结构中删除。

你问的线

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

由于快照包含一系列键:值对,所以String:AnyObject有效。

这条线因Swift 3而改变

 for item in (snapshot?.children)! 

但除此之外,代码的作品。

试试这个以确保你正在阅读正确的节点。 这读取上述结构并打印出每个引擎types。 (testing和工作)

  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!) } } }) 

我想你在firebase数据的结果键值中有一个额外的数组。

  • 您应该尝试删除该数组或

  • 您可以从数组的第一个索引检索字典,如:

     // .. your code let snapshotValue = (snapshot.value as! [AnyObject])[0] as! [String:AnyObject]; // .. your code 

在你的结构类中确保这些东西:

  • 避免声明你的variables为:Int? 因为这实际上是零,改变他们:Int!

  • 您的firebase中的密钥是一个Int,并且您正在声明您的密钥在结构中作为let key: String! ,将其更改为let key: Int!

  • 将您的快照字典声明视为let snapshotValue = snapshot.value as! [AnyHashable:Any] let snapshotValue = snapshot.value as! [AnyHashable:Any] (按照swift 3)

然后你的init函数:

只要改变一下

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

 let snapshotValue = (snapshot.value as! NSArray)[0] as! [String:AnyObject]