First, I have checked these answers that do not help me : Swift JSON error, Could not cast value of type '__NSArrayM' (0x507b58) to 'NSDictionary' (0x507d74)
首先,我已经检查了这些答案,不帮我:斯威夫特JSON错误,无法投类型的值“__NSArrayM”(0x507b58)为“NSDictionary中”(0x507d74)
Get data from Firebase
从Firebase获取数据
When retrieving data from Firebase (3.x), I have an error that occurs which is :
从Firebase(3.x)检索数据时,出现错误,即:
Could not cast value of type '__NSArrayM' (0x10ca9fc30) to 'NSDictionary' (0x10caa0108).
with this code and tree :
使用此代码和树:
Tree :
Retrieving 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 - To manage the data
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
}
on the line : let snapshotValue = snapshot.value as! [String:AnyObject]
在线:让snapshotValue = snapshot.value为! [字符串:AnyObject]
I suppose that is due to the snapshot value that can't be retrieved under [String:AnyObject]
because of the Int
below. (It is working when I only have String
in another case).
我想这是由于在[String:AnyObject]下无法检索的快照值,因为下面的Int。 (当我在另一个案例中只有String时,它正在工作)。
I also know that Firebase "converts" the JSON tree to these objects [link]:
我也知道Firebase将JSON树“转换”为这些对象[link]:
NSString
NSNumber
NSArray
NSDictionnary
but I can't figure out what has to be changed in the snapshot.value line to make it work.
但我无法弄清楚snapshot.value行中需要更改的内容才能使其正常工作。
Thanks for your help.
谢谢你的帮助。
EDIT : I just sent a troubleshooting request. Will post updates. EDIT 2: See Jay's answer. In my case the tree was wrong.
编辑:我刚刚发送了一个故障排除请求。将发布更新。编辑2:看杰伊的答案。在我的情况下,树是错的。
2
I took your code and shrunk it down a bit for testing, and it's working. (note Firebase 2.x on OS X and Swift 3 but the code is similar)
我拿了你的代码并将其缩小了一点以进行测试,并且它正在工作。 (注意OS X和Swift 3上的Firebase 2.x,但代码类似)
Firebase structure:
"what-am" : {
"results" : [ {
"code" : "738/B738",
"data" : "Boeing",
"engines" : "Rolls"
}, {
"code" : "727/B727",
"data" : "Boeing",
"engines" : "Pratt"
} ]
}
Here's the Planes struct
这是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
}
}
and then the code that reads in two planes, populates and array and then prints the array.
然后读入两个平面的代码,填充和数组,然后打印数组。
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)
}
})
and finally the output
最后输出
[Swift_Firebase_Test.Planes(code: 738/B738, data: Boeing, engines: Rolls),
Swift_Firebase_Test.Planes(code: 727/B727, data: Boeing, engines: Pratt)]
Key and name are nil as I removed then from the Planes structure.
当我从Planes结构中移除时,键和名称为nil。
The line you asked about
你问过的那条线
let snapshotValue = snapshot.value as! [String:AnyObject]
is valid as the snapshot contains a series of key:value pairs so String:AnyObject works.
有效,因为快照包含一系列键:值对,因此String:AnyObject有效。
This line changed due to Swift 3
由于Swift 3,此行已更改
for item in (snapshot?.children)!
but other than that, the code works.
但除此之外,代码有效。
Try this to ensure you are reading the correct node. This reads the above structure and prints out each engine type. (tested and works)
试试这个以确保您正在读取正确的节点。这将读取上述结构并打印出每种引擎类型。 (测试和工作)
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
I think you are having an extra array in your results key-value on the firebase data.
我认为你在firebase数据的结果键值中有一个额外的数组。
You should try removing that array or
你应该尝试删除该数组或
You may retrieve dictionary from first index of the array like;
您可以从数组的第一个索引中检索字典,如:
// .. your code
let snapshotValue = (snapshot.value as! [AnyObject])[0] as! [String:AnyObject];
// .. your code
0
In your struct class make sure of these things:-
在你的struct类中确保这些东西: -
Avoid declaring your variables as :Int?
because that's practically nil, change them to :Int!
避免将变量声明为:Int?因为那几乎是零,所以改为:Int!
Your key in your firebase is an Int and you are declaring your key in struct as let key: String!
, Change it to let key: Int!
你的firebase中的密钥是一个Int,你在struct中声明你的密钥,因为let:String !,把它更改为let key:Int!
Prefer your snapshot dictionary declaration as let snapshotValue = snapshot.value as! [AnyHashable:Any]
(as per swift 3)
首选快照字典声明,因为snapshotValue = snapshot.value为! [AnyHashable:Any](根据swift 3)
Then your init function to :-
然后你的init函数: -
Just change the line
只需改变线条
let snapshotValue = snapshot.value as! [String:AnyObject]
To
let snapshotValue = (snapshot.value as! NSArray)[0] as! [String:AnyObject]
0
update FIRDataSnapshot to DataSnapshot Swift 4
将FIRDataSnapshot更新为DataSnapshot Swift 4