首先,我检查了这些对我没有帮助的答案: Swift JSON error, Could not cast value of type '__NSArrayM' (0x507b58) to 'NSDictionary' (0x507d74)
从Firebase(3.x)检索数据时,出现错误:
Could not cast value of type '__NSArrayM' (0x10ca9fc30) to 'NSDictionary' (0x10caa0108).
使用此代码和树:
树:
检索功能:
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
时,它正在工作。)
我也知道Firebase"转换"这些对象[link]的JSON树:
NSString
NSNumber
NSArray
NSDictionnary
但是我无法弄清楚snapshot.value行中需要更改的内容才能使其正常工作。
感谢您的帮助。
编辑:我刚刚发送了一个问题排查请求。将发布更新。 编辑2:看看周杰伦的回答。在我的情况下,树是错误的。
答案 0 :(得分:2)
我拿了你的代码并将其缩小了一点以进行测试,并且它正在运行。 (注意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"
} ]
}
这是Planes struct
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)]
当我从Planes结构中移除时,键和名称为nil。
您询问的问题
let snapshotValue = snapshot.value as! [String:AnyObject]
有效,因为快照包含一系列键:值对,因此String:AnyObject可以工作。
由于Swift 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!)
}
}
})
答案 1 :(得分:0)
在你的struct类中确保以下内容: -
避免将变量声明为:Int?
,因为这几乎为零,将其更改为:Int!
您的firebase中的密钥是一个Int,您将结构中的密钥声明为let key: String!
,将其更改为let key: Int!
首选快照字典声明为 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]
答案 2 :(得分:0)
我认为你在firebase数据的结果键值中有一个额外的数组。
您应该尝试删除该数组或
您可以从数组的第一个索引中检索词典,如;
// .. your code
let snapshotValue = (snapshot.value as! [AnyObject])[0] as! [String:AnyObject];
// .. your code
答案 3 :(得分:0)
将FIRDataSnapshot更新为DataSnapshot Swift 4
答案 4 :(得分:0)
下面是Swift 4的示例。您需要将FIRDataSnapshot更改为DataSnapshot
func fetchChats(chatId: String) {
ref.child("chats").child("SomeChildId").observe(.value) { (snapshot) in
for child in snapshot.children {
let data = child as! DataSnapshot //<--- Update this line
let dict = data.value as! [String: AnyObject]
let message = dict["message"]
print(message!)
}
}
}