2016-10-08 72 views
4

首先,我检查了这些答案不帮我: Swift JSON error, Could not cast value of type '__NSArrayM' (0x507b58) to 'NSDictionary' (0x507d74)火力地堡检索数据 - 无法施展值

Get data from Firebase

从火力地堡(3.X)检索数据时,我有一个错误发生这就是:

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

与此代码和树:

树:

enter image description here

检索功能:

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 - 为了管理数据

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]

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

我也知道,火力地堡的JSON树 “转换” 将这些对象[link]

  • NSString
  • NSNumber
  • NSArray
  • NSDictionnary

,但我不能找出需要改变的地方napshot.value行使其工作。

感谢您的帮助。

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

+0

给你的JSON树结构和代码到你找回它。 – Dravidian

+0

@Dravidian在这里,你去! – Antoine

+0

有'init(snapshot:FIRDataSnapshot)'构造函数以前工作? – eshirima

回答

2

我把你的代码缩小了一点,以便进行测试,它正在工作。 (注意,OS X火力地堡2.x和斯威夫特3,但该代码是相似的)

火力地堡结构:

"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] 

是有效的快照包含一系列关键的:值对这样的字符串:AnyObject作品。

此行改变由于斯威夫特3

for item in (snapshot?.children)! 

但除此之外,代码工作。

试试这个以确保您正在阅读正确的节点。这读取上述结构并打印出每种引擎类型。 (测试和工程)

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

'.child(byAppendingPath:)'已弃用。 – eshirima

+0

所以我应该将snapshotValue行更改为(snapshot?.children)中的for项目? – Antoine

+0

@EmilDavid是的,我意识到这是贬低我的笔记在顶部(Firebase 2.x),但是,Firebase表示,他们'仍然支持'前进一段时间'2.x,当你有一个macOS的代码库,你不能使用3. – Jay

0

在你的结构类,确保这些事情: -

  • 可以避免声明的变量为:Int?,因为这是几乎为零,将其更改为:Int!

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

  • 身高快照字典声明为let snapshotValue = snapshot.value as! [AnyHashable:Any](根据SWIFT 3)

然后在你的初始化函数: -

只需更改行

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

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

所以我改变了Int和快照声明,但我仍然有同样的错误。 – Antoine

+0

错误发生在这个精确的线上,所以我不能打印() – Antoine

+0

对于“let snapshotValue = snapshot.value ...”行我有一个错误=>“类型'[字符串:AnyObject]'的值有没有成员'价值' – Antoine

0

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

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

  • 您可以检索从数组的第一个索引字典等;

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

不,无法正常工作错误:无法将'__NSDictionnaryM'类型的值转换为'NSArray' – Antoine