Firebase完成下载后如何直接执行代码?

时间:2016-12-20 10:24:29

标签: ios swift firebase firebase-realtime-database

我有代码需要在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数据库下载我想要的项目,但在完成之前将在其后运行任何代码。如何制作它以便我可以选择在下载完成后立即执行代码块?

3 个答案:

答案 0 :(得分:2)

这是因为 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()
  })
}

答案 1 :(得分: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
            }
        }
     }
  })
}

答案 2 :(得分:1)

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