将观察 .value 转换为 .child 快速添加

Posted

技术标签:

【中文标题】将观察 .value 转换为 .child 快速添加【英文标题】:Convert observe .value to .childAdded in swift 【发布时间】:2017-10-03 16:28:44 【问题描述】:

目前,我在将 Firebase 数据库中的数据加载到数组中的这段代码中遇到了一些问题。由于这是在 viewDidLoad 内部,我必须在将数据加载到其中之前清空我的数组food = [],如果我不这样做,它将复制所有对象,并且第二次加载时我将重复两次,第三次加载三次等等...但是由于多种原因,这不是一个好的解决方法,所以我想要的是它只会使用.childAdded 从数据库中添加新对象但是如果我只是用.childAdded 切换出.value 它会崩溃,我在这条线上得到一个Thread 1: signal SIGABRTlet dict = user_snap.value as! [String: String?]。我对 swift 很陌生,不知道如何解决这个问题,非常感谢一些帮助。

let parentRef = Database.database().reference().child("Recipes")
let storage = Storage.storage()

parentRef.observe(.value, with:  snapshot in

        if ( snapshot.value is NSNull ) 

            // DATA WAS NOT FOUND
            print("– – – Data was not found – – –")

         else 

            //Clears array so that it does not load duplicates
            food = []

            // DATA WAS FOUND
            for user_child in (snapshot.children) 

                let user_snap = user_child as! DataSnapshot
                let dict = user_snap.value as! [String: String?]

                //Defines variables for labels
                let recipeName = dict["Name"] as? String
                let recipeDescription = dict["Description"] as? String
                let downloadURL = dict["Image"] as? String

                let storageRef = storage.reference(forURL: downloadURL!)

                storageRef.getData(maxSize: 1 * 1024 * 1024)  (data, error) -> Void in

                    let recipeImage = UIImage(data: data!)

                    food.append(Element(name: recipeName!, description: recipeDescription!, image: recipeImage!))
                    self.tableView.reloadData()
                
            
        
    )

【问题讨论】:

用这一行更新你的代码以避免崩溃if let dict = user_snap.value as? [String: String?] 。还要检查 user_snap 对象的类型。当您的应用程序崩溃时,我确信它没有字典对象。 @Surjeet 我在 里面放了什么? 注释行“为标签定义变量”之后的代码。我已经在 for 循环中为您提供了第二行的更新版本 @Surjeet ok 将注释后的所有代码添加到括号中,它没有崩溃但是我的 tableView 现在是空的,数组也是。 @Surjeet 换句话说:括号内的代码不会运行,它会跳过它。 【参考方案1】:
let dict = user_snap.value as! [String: String?]

代替

let dict = snapshot.value as! Dictionary<String, String>

也许你可以做空测试:

let dict = snapshot.value as! Dictionary<String, String>

if let recipeName = dict["Name"] as String!, let recipeDescription = dict["Description"] as String!, let downloadURL = dict["Image"] as String! 
    let storageRef = storage.reference(forURL: downloadURL)

    storageRef.getData(maxSize: 1 * 1024 * 1024)  (data, error) -> Void in

        let recipeImage = UIImage(data: data!)

        food.append(Element(name: recipeName, description: recipeDescription, image: recipeImage!, downloadURL: downloadURL))
        self.tableView.reloadData()                        
                        
else 
    print("Error! Could not decode data")                    

【讨论】:

是的,你太棒了!谢谢,但是您遗漏了我的一些代码并更改了一些变量名,因此我对其进行了编辑和修复。【参考方案2】:

试试这个。它应该工作

for child in snapshot.children.allObjects as! [FIRDataSnapshot] 

let dict = child.value as! Dictionary<String, Any>

//.....

【讨论】:

我在let dict = child.value as! Dictionary&lt;String, Any&gt; 上得到Thread 1: signal SIGABRT,在调试器中显示Could not cast value of type 'NSTaggedPointerString'

以上是关于将观察 .value 转换为 .child 快速添加的主要内容,如果未能解决你的问题,请参考以下文章

使用快速添加的 .Value/.Child 从 Firebase 检索数据时遇到问题

如何快速将 Int 转换为 int?

他们如何快速(记住)将十进制转换为十六进制?

Firebase 使用 .value 观察者获取数据不起作用

Swift -Firebase 可以同时发布和观察

将 AppKit/UIKit 中的 Key-Value Observation 转换为 Combine 和 SwiftUI