从firebase调用数据需要完成处理程序?

Posted

技术标签:

【中文标题】从firebase调用数据需要完成处理程序?【英文标题】:Completion handler needed for calling data from firebase? 【发布时间】:2020-02-24 21:50:18 【问题描述】:

我正在尝试从 firebase 调用数据。问题是,数据嵌套很深,我认为我无法改变它。

所以我尝试从 firebase 调用值,然后我可以使用它来引用新值。 当我的 for 循环在下一个阶段被调用之前没有完成时就会出现问题,这意味着我下一个阶段的字典计数是 0,所以我的下一个函数没有被调用?

有没有办法充分做到这一点?

请帮忙?

这是我的代码:

func fetchBuyer(search: String, user: String, completion: @escaping ([Post]) -> (), withCancel cancel: ((Error) -> ())?) 
    let ref = Database.database().reference().child("posts").child(user).child(search).child("purchases")
    ref.observeSingleEvent(of: .value, with:  (snapshot) in
        guard let dictionaries = snapshot.value as? [String: Any] else 
            completion([])
            return
        

        let keys: [String] = dictionaries.map( $0.key )
        var newdictionaries = [String: String]()

        for i in keys 
            let newref = Database.database().reference().child("posts").child(user).child(search).child("purchases").child(i).child("purchaser")
            newref.observeSingleEvent(of: .value, with:  (snapshot) in
                newdictionaries[i] = snapshot.value as? String
                print("THESE ARE MY PURCHASES ID-->", newdictionaries.values)///prints out ["-M0pTHtZXYUVQT7DCLj-", "-M0pU79uQCCnBunAEkJN"]
            )
        

        var buyerPosts = [Post]()
        print("newdictionaries.count--->", newdictionaries.count)//this print is 0
        newdictionaries.forEach( (postId, value) in
            Database.database().fetchPost(withUID: user, postId: postId, completion:  (post) in
                buyerPosts.append(post)
                if buyerPosts.count == newdictionaries.count
                    completion(buyerPosts)
                
            )
        )
    )  (err) in
        print("Failed to fetch posts for buyers:", err)
        cancel?(err)
    

尝试回答:

            let g = DispatchGroup()  //// 1
           for i in keys
               g.enter()   //// 2
               let newref = Database.database().reference().child("posts").child(user).child(search).child("purchases").child(i).child("purchaser")
            print("now")
            newref.observeSingleEvent(of: .value, with:  (snapshot)
                       newdictionaries[i] = snapshot.value as? String
                        print("print new dictionaries-->", newdictionaries)
                       // complete here
                Database.database().fetchPost(withUID: user, postId: newdictionaries[i]!, completion:  (post) in
                                buyerPosts.append(post)
                                g.leave() //////// 3
                         )
                    )
             
         g.notify(queue: DispatchQueue.main) 
            print("finished!!!")
           completion(buyerPosts)
         

【问题讨论】:

您可能对 DispatchGroup 感兴趣,leave()enter()notify() 现在代码格式正确,for i in keys 后面的代码将在从 Firebase 返回数据之前调用,Database.database().fetchPost1 后面有闭包。如果您移动代码,从 firebase 闭包中的 var buyerPosts = [Post]() 开始,它将“更好”地工作。但是,这不是解决方案。要找到解决方案,我们需要了解您的结构以及您想要获取的数据。另外,如果您正在开发中,为什么不能更改结构?使用控制台复制并粘贴结构的 sn-p->导出 JSON 和 【参考方案1】:

你需要一个调度组并嵌套调用

    let g = DispatchGroup()  //// 1

    for i in keys
        g.enter()   //// 2
        let newref = Database.database().reference().child("posts").child(user).child(search).child("purchases").child(i).child("purchaser")
             newref.observeSingleEvent(of: .value, with:  (snapshot) 
                newdictionaries[i] = snapshot.value as? String 
                // complete here 
                    Database.database().fetchPost(withUID: user, postId: postId, completion:  (post) in
                         buyerPosts.append(post)
                         g.leave() //////// 3
                  )

             )
      

 /// 4
  g.notfiy(queue.main) 
    completion(buyerPosts)
  

【讨论】:

我收到错误消息:Contextual type for closure argument list expects 1 argument, which cannot be implicitly ignored 上线-observeSingleEvent?见编辑。

以上是关于从firebase调用数据需要完成处理程序?的主要内容,如果未能解决你的问题,请参考以下文章

如何调用组合多个完成处理程序以将数据组合到一个新数组

尝试使用完成处理程序从 google firebase 获取数据时遇到问题

未调用 Firebase 存储完成处理程序

使用 Firebase 的 Swift 完成处理程序

使用完成处理程序按顺序执行操作

Firebase 和 Swift:异步调用、完成处理程序