【问题标题】:How to execute code directly after Firebase finishes downloading?Firebase下载完成后如何直接执行代码?
【发布时间】:2016-12-20 10:24:28
【问题描述】:

我有一些代码需要在 Firebase 完成下载我指定它事先下载的内容后立即执行。问题是此代码始终在下载完成之前运行。

if currentVersionNumber < newVersionNumber {
            print("Feed: button donwloading cards")
            //self.databaseButton.setTitle("Downloading New Cards...", for: .normal)
            ref.observe(.value, with: { snapshot in
                print("Feed: Checking for new cards from firebase")
                for item in snapshot.children {
                    // Download in memory with a maximum allowed size of 1MB (1 * 1024 * 1024 bytes)
                    cardRef.data(withMaxSize: 1 * 1024 * 1024) { (data, error) -> Void in
                        if (error != nil) {
                            // Uh-oh, an error occurred!
                            print("Feed: error occured")
                            print(error)
                        } else {
                            // Data for "images/island.jpg" is returned
                            cards.imageName = data!
                            print("Feed: downloaded \(cards.name)")
                        }
                    }
                    // add to updated list of cards

                    updateCards.append(cards);
                }
            })

        } else {
             print("Feed: cards are up to date. \(currentVersionNumber)")
        }

    })

此代码从 Firebase 数据库下载我想要的项目,但会在它之后运行任何代码,在它完成之前。如何制作,以便我可以选择在下载完成后立即执行代码块?

【问题讨论】:

    标签: ios swift firebase firebase-realtime-database


    【解决方案1】:

    发生这种情况是因为 Firebase 的所有更新都发生在后台线程中,并且您的代码在主线程中执行。要处理此调用,请在具有闭包的函数中调用您的 firebase 方法,该闭包会在您的 firebase 下载完成后立即被调用。

    例如:

    在你的viewDidLoad:

    override func viewDidLoad() {
    
       super.viewDidLoad()
    
       fetchData {
    
           //do whatever action you wish to perform on download completion
           mainTableView.reloadData()
       }
    }
    
    func fetchData(andOnCompletion completion:@escaping ()->()){
    
       ref.observe(.value, with: { snapshot in
                print("Feed: Checking for new cards from firebase")
                for item in snapshot.children {
                    // Download in memory with a maximum allowed size of 1MB (1 * 1024 * 1024 bytes)
                    cardRef.data(withMaxSize: 1 * 1024 * 1024) { (data, error) -> Void in
                        if (error != nil) {
                            // Uh-oh, an error occurred!
                            print("Feed: error occured")
                            print(error)
                        } else {
                            // Data for "images/island.jpg" is returned
                            cards.imageName = data!
                            print("Feed: downloaded \(cards.name)")
                        }
                    }
                    // add to updated list of cards
    
                    updateCards.append(cards);
                }
             //call the block when done processing          
         completion()
      })
    }
    

    【讨论】:

    • 我看到添加了一个答案,但我没有意识到它们有多接近。如果我不花一些时间在上面,我会删除它,但我想 2 个例子比一个好。请注意,您没有将 updateCards.append 移动到内部闭包。
    • 这似乎对我不起作用,因为它在完成下载之前调用完成
    【解决方案2】:

    这些网络请求是异步运行的,因此它们之后的任何代码都将在网络请求完成时继续运行。

    您应该将 updateCards.append(cards) 移动到内部闭包内,这样它才会在第二个闭包完成之前被调用,然后如果您有其他代码需要在完成后运行,您可以将其移入此函数或使用带有完成处理程序的闭包,以确保在您运行更多依赖于响应的代码之前完成所有网络请求。

    getCardData { [weak self] in
    // do whatever you need to do after completion
    }
    
    func getCardData(_ completion: () -> ()) {
    print("Feed: button donwloading cards")
    //self.databaseButton.setTitle("Downloading New Cards...", for: .normal)
    ref.observe(.value, with: { snapshot in
        print("Feed: Checking for new cards from firebase")
        for item in snapshot.children {
            // Download in memory with a maximum allowed size of 1MB (1 * 1024 * 1024 bytes)
            cardRef.data(withMaxSize: 1 * 1024 * 1024) { (data, error) -> Void in
                if (error != nil) {
                    // Uh-oh, an error occurred!
                    print("Feed: error occured")
                    print(error)
                    completion() // this is where you would normally throw an error or have a closure that accepts an optional error you would pass in to know it failed
                } else {
                    // Data for "images/island.jpg" is returned
                    cards.imageName = data!
                    print("Feed: downloaded \(cards.name)")
                    updateCards.append(cards);
                    completion()// now you know all network requests are complete
                }
            }
         }
      })
    }
    

    【讨论】:

    • 这两个答案似乎都不起作用,在下载完成之前调用完成
    【解决方案3】:

    通过在下载中添加 if 语句来检查附加到 updateCards 的卡片数量是否等于快照中的卡片数量,从而设法解决了我的问题。感谢回答这个问题的两位,因为我也使用了 completion() 方法,很高兴我去了解这个我不知道存在的概念。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-07
      • 2013-08-21
      • 2012-02-08
      • 2014-10-27
      • 1970-01-01
      • 2022-01-10
      相关资源
      最近更新 更多