Firebase 查询结果 SWIFT 的奇怪行为

Posted

技术标签:

【中文标题】Firebase 查询结果 SWIFT 的奇怪行为【英文标题】:Strange behaviour on Firebase query result SWIFT 【发布时间】:2019-01-16 06:41:03 【问题描述】:

我在 let itemToAdd = snapshot.childSnapshot(forPath: "Shopa 从 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 值时:完成被调用,但我没有得到快照打印。 第二:查询条目并查找字符串值时:不会调用完成,但快照会打印带有值的正确条目。

任何人都可以看看这里发生了什么吗?

【问题讨论】:

您的店铺名称在某处为空。所以不要使用'as!'尝试使用“如果让” 我正在使用应该给我结果的搜索值。如何检查我获得的快照中的内容? 在运行 for 循环之前尝试记录 snapshot.children。您可能会看到值 我 printend childSnapshot 并且它有一个结果:`childSnapshot is: Snap (Arma Wed Mor) "Closing Time" = 41230; “开放时间”= 40830; “店铺名称” = Armaroli; ´ 所以查询正在寻找正确的数据。我只想从中获取店铺名称 @sanman。有趣的是,我将搜索重复到一个应该返回 2 家商店的值,但我仍然只得到与以前相同的值。可能是因为我在 for in 循环内打印childSnapshot?我会尝试在循环之前打印snapshot.children 【参考方案1】:

我发现问题出在我投射查询结果的方式上。 将其转换为 [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()

【讨论】:

以上是关于Firebase 查询结果 SWIFT 的奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章

firebase 存储 cors 奇怪的行为

在 iOS 上接收来自 firebase 的通知的奇怪行为

Firebase/React/Redux 组件有奇怪的更新行为,状态应该没问题

Firebase 和 swiftUI,监听实时更新奇怪的行为怪异

没有结果时,Firebase 查询不调用块

奇怪的 chrome 媒体查询行为