使用 Swift 闭包和 Firebase 处理异步数据
Working with asynchronous data with Swift closures and Firebase
我需要调用特定的 Firebase 引用并取回数据。此操作将在多个 VC 内进行,因此我希望有一个 class,我将在其中调用 Firebase 的各种函数。例如,如果我想获取所有文章,我将调用我的 FirebaseHelpers class,并使用 method/closure fetchArticles()。这样,如果我想重构某些东西,我只会在 FirebaseHelpers class 中进行,而不会遍历所有 VCs.
FirebaseHelpers
import UIKit
import Firebase
class FirebaseHelpers {
func fetchArticles(completion: @escaping ([Article]?, Error?) -> Void) {
var articles = [Article]()
let articlesQuery = Database.database().reference().child("articles").queryOrdered(byChild: "createdAt")
articlesQuery.observe(.value, with: { (snapshot) in
guard let articlesDictionaries = snapshot.value as? [String : Any] else { return }
articlesDictionaries.forEach({ (key, value) in
guard let articleDictionary = value as? [String: Any] else { return }
// build articles array
let article = Article(dictionary: articleDictionary)
print("this is article within closure \(article)")
articles.append(article)
})
})
completion(articles, nil)
}
}
任意viewController
let firebaseHelpers = FirebaseHelpers()
var articles = [Article]() {
didSet {
self.collectionView.reloadData()
}
}
// this is inside viewDidLoad()
firebaseHelpers.fetchArticles { (articles, error) in
guard let articles = articles else { return }
print("articles \(articles)")
self.articles = articles
}
问题是我没有得到任何结果。在我的 VC 中,print("articles(articles)") 将 return 一个 空数组 。但是在我的 FirebaseHelpers fetchArticles() 中, print("this is article within closure (article)") 将打印文章 就好了 .
知道为什么会这样吗?
提前致谢。
您可以在异步函数中移动 completion
:
class FirebaseHelpers {
func fetchArticles(completion: @escaping ([Article]?, Error?) -> Void) {
var articles = [Article]()
let articlesQuery = Database.database().reference().child("articles").queryOrdered(byChild: "createdAt")
articlesQuery.observe(.value, with: { (snapshot) in
guard let articlesDictionaries = snapshot.value as? [String : Any] else { return }
articlesDictionaries.forEach({ (key, value) in
guard let articleDictionary = value as? [String: Any] else { return }
// build articles array
let article = Article(dictionary: articleDictionary)
print("this is article within closure \(article)")
articles.append(article)
})
completion(articles, nil) // <- move here
})
// completion(articles, nil) // <- remove
}
}
否则 completion
将在您的异步函数之前被调用。
我需要调用特定的 Firebase 引用并取回数据。此操作将在多个 VC 内进行,因此我希望有一个 class,我将在其中调用 Firebase 的各种函数。例如,如果我想获取所有文章,我将调用我的 FirebaseHelpers class,并使用 method/closure fetchArticles()。这样,如果我想重构某些东西,我只会在 FirebaseHelpers class 中进行,而不会遍历所有 VCs.
FirebaseHelpers
import UIKit
import Firebase
class FirebaseHelpers {
func fetchArticles(completion: @escaping ([Article]?, Error?) -> Void) {
var articles = [Article]()
let articlesQuery = Database.database().reference().child("articles").queryOrdered(byChild: "createdAt")
articlesQuery.observe(.value, with: { (snapshot) in
guard let articlesDictionaries = snapshot.value as? [String : Any] else { return }
articlesDictionaries.forEach({ (key, value) in
guard let articleDictionary = value as? [String: Any] else { return }
// build articles array
let article = Article(dictionary: articleDictionary)
print("this is article within closure \(article)")
articles.append(article)
})
})
completion(articles, nil)
}
}
任意viewController
let firebaseHelpers = FirebaseHelpers()
var articles = [Article]() {
didSet {
self.collectionView.reloadData()
}
}
// this is inside viewDidLoad()
firebaseHelpers.fetchArticles { (articles, error) in
guard let articles = articles else { return }
print("articles \(articles)")
self.articles = articles
}
问题是我没有得到任何结果。在我的 VC 中,print("articles(articles)") 将 return 一个 空数组 。但是在我的 FirebaseHelpers fetchArticles() 中, print("this is article within closure (article)") 将打印文章 就好了 .
知道为什么会这样吗?
提前致谢。
您可以在异步函数中移动 completion
:
class FirebaseHelpers {
func fetchArticles(completion: @escaping ([Article]?, Error?) -> Void) {
var articles = [Article]()
let articlesQuery = Database.database().reference().child("articles").queryOrdered(byChild: "createdAt")
articlesQuery.observe(.value, with: { (snapshot) in
guard let articlesDictionaries = snapshot.value as? [String : Any] else { return }
articlesDictionaries.forEach({ (key, value) in
guard let articleDictionary = value as? [String: Any] else { return }
// build articles array
let article = Article(dictionary: articleDictionary)
print("this is article within closure \(article)")
articles.append(article)
})
completion(articles, nil) // <- move here
})
// completion(articles, nil) // <- remove
}
}
否则 completion
将在您的异步函数之前被调用。