我在let itemToAdd = snapshot.childSnapshot(forPath: "Shop
行上遇到此错误,该函数从Firebase检索数据。
Could not cast value of type 'NSNull' (0x1118c8de0) to 'NSString' (0x10dda45d8).
中控制台的输出。
我想做的是按一个值
opening Time
过滤数据库排序,而不是从快照中返回的条目中获取另一个值Shop Name
。
这是函数:
func filterOpenShops(enterDoStuff: @escaping (Bool) -> ()) {
ref = Database.database().reference().child("Continent").child("Europe").child("Country").child("Italy").child("Region").child("Emilia-Romagna").child("City").child("Bologna").child("Shops").child("Shops Opening Times")
let query = ref?.queryOrdered(byChild: "Opening Time").queryStarting(atValue: openingTimeQueryStart).queryEnding(atValue: openingTimeQueryEnd)
query?.observe(.value, with: { (snapshot) in
for childSnapshot in snapshot.children {
// new modification
if childSnapshot is DataSnapshot {
let itemToAdd = snapshot.childSnapshot(forPath: "Shop Name").value as! String // gets the open shop from snapshot
self.availableShopsArray.append(itemToAdd)
print(snapshot.children)
print(" Open Shops are \(self.availableShopsArray)")
}
}
// still asynchronous part
enterDoStuff(true)
// call next cascade function filterClosedShops only when data
})
// Sychronous part
print("opening query start is \(openingTimeQueryStart) and opening query end is \(openingTimeQueryEnd)")
} // end of filterOpenShops()
编辑:
I rewrote the function as:
func filterOpenShops(enterDoStuff: @escaping (Bool) -> ()) {
// get from Firebase snapshot all shops opening times into an array of tuples
//shopOpeningTimeArray:[(storeName: String, weekdayNumber: String, opening1: Sring, closing1: String, opening2:String, closing2: String)]
ref = Database.database().reference().child("Continent").child("Europe").child("Country").child("Italy").child("Region").child("Emilia-Romagna").child("City").child("Bologna").child("Shops").child("Shops Opening Times")
let query = ref?.queryOrdered(byChild: "Opening Time").queryStarting(atValue: String(describing: openingTimeQueryStart)).queryEnding(atValue: String(describing :openingTimeQueryEnd))
query?.observe(.value, with: { (snapshot) in // original is ok
// guard let data = snapshot.value as? [String:String] else { return }
for childSnapshot in snapshot.children {
print("snapshot is: \(childSnapshot)")
print("snapshot.childrend is: \(snapshot.children)")
guard let data = snapshot.value as? [String:String] else { return }
let itemToAdd = data["Shop Name"]
self.availableShopsArray.append(itemToAdd!)
print("Open Shop is: \(String(describing: itemToAdd))")
print(" Open Shops are \(self.availableShopsArray)")
}
// still asynchronous part
enterDoStuff(true)
// call next cascade function filterClosedShops only when data
print(" Open Shops are \(self.availableShopsArray)")
})
print("opening query start is \(openingTimeQueryStart) and opening query end is \(openingTimeQueryEnd)")
} // end of filterOpenShops()
但是我仍然得到一个空对象,而不是预期的[String:String]。
在Firebase中创建条目的函数是:
func postOpeningTime() {
// if shopNameTextfield.text != nil && openingTimeTextfield.text != nil && closingTimeTextfield.text != nil {
let shopName = shopNameTextfield.text!
let openingTime = openingTimeTextfield.text!
let closingTime = closingTimeTextfield.text!
// } else {return}
let post: [String:String] = [
"Shop Name" : shopName ,
"Opening Time" : openingTime ,
"Closing Time" : closingTime
]
var ref: DatabaseReference!
ref = Database.database().reference()
ref?.child("Continent").child("Europe").child("Country").child("Italy").child("Region").child("Emilia-Romagna").child("City").child("Bologna").child("Shops").child("Shops Opening Times").childByAutoId().setValue(post)
}
现在我有两个行为:
1st:查询条目并查找Int值时:会调用complete,但是没有快照打印。 第二:查询条目并找到String值时:不会调用完成,但快照会打印正确的值。
任何人都可以发现这里发生的事情吗?
答案 0 :(得分:0)
我发现问题出在我投射查询结果的方式上。 将其强制转换为[String:String]会返回,因为当条目参数的所有值均为String时,上次拍摄实际上是[String [String:String]],但是当我将打开时间和关闭时间更改为Int时,我不得不以[String [String:Any]]读取快照。 所以最后一个功能是:
func filterOpenShops(setCompletion: @escaping (Bool) -> ()) {
// Empty the array for beginning of the search
self.availableShopsArray.removeAll()
var ref = Database.database().reference()
ref.child("Continent").child("Europe").child("Country").child("Italy").child("Region").child("Emilia-Romagna").child("City").child("Bologna").child("Shops").child("Shops Opening Times").queryOrdered(byChild: "Opening Time").queryStarting(atValue: openingTimeQueryStart).queryEnding(atValue: openingTimeQueryEnd).observe(.value) { (snapshot) in
print(snapshot)
if let data = snapshot.value as? [String : [String : Any]] {
for (_, value) in
data {
let shopName = value["Shop Name"] as! String
let active = value["Active"] as! String
if active == "true" {
self.availableShopsArray.append(shopName)
print("Shop_Name is :\(shopName)")
print("self.availableShopsArray is: \(self.availableShopsArray)")
}
}
} else {
print("No Shops")
}
// still asynchronous part
setCompletion(true)
// call next cascade function filterClosedShops only when data retrieving is finished
self.filterClosedShops(setCompletion: self.completionSetter)
print(" 1 Open Shops are \(self.availableShopsArray)")
}
} // end of filterOpenShops()