所以我有firebase的问题,因为它是异步的,我不知道如何正确使用它。我的应用程序有待售产品,我从firebase数据库和firebase存储(图片)获得。问题是我不知道何时或如何重新加载我的UITableView以获取所有数据而不会出现nil错误。而且它更复杂,因为首先我需要从firebase获取我的salePost信息,然后才能获得用户信息,这也是在tableview单元格中。
这就是我获得salesPosts的方式
func getSalePosts() -> [SalePost]{
var salePosts = [SalePost]()
FIR_DATABASE_SALE_POSTS.queryLimitedToFirst(NUMBER_OF_LOADED_POSTS).observeEventType(.Value, withBlock: { (snapshot) in
for snap in snapshot.children{
let imgString = snap.value["image"] as! String!
let imgNSURL = NSURL(string: imgString)
let imgNSDATA = NSData(contentsOfURL: imgNSURL!)
let downloadedImg = UIImage(data: imgNSDATA!)
let newSalePost = SalePost(title: snap.value["title"] as! String!,
userUID: snap.value["authorUID"] as! String!,
postBody: snap.value["body"] as! String!,
amountAvailable: snap.value["amountAvailable"] as! String!,
unit: snap.value["unit"] as! String!,
price: snap.value["price"] as! String!,
image: downloadedImg!)
salePosts.append(newSalePost)
print("num of posts \(salePosts.count)")
}
}) { (error) in
print(error.localizedDescription)
}
return salePosts
}
这是获取UserInfo的func(我将从salePost对象获取“userUID”)
func getProducer(userUID:String) -> Producer{
var newProducer:Producer?
FIR_DATABASE_USERS.child(userUID).observeEventType(.Value, withBlock: { (snap) in
print(snap.description)
let imgString = snap.value!["profilePic"] as! String!
let imgNSURL = NSURL(string: imgString)
let imgNSDATA = NSData(contentsOfURL: imgNSURL!)
let downloadedImg = UIImage(data: imgNSDATA!)
let someProducer = Producer(
displayName: snap.value!["displayName"] as! String!,
address: snap.value!["address"] as! String!,
mobile: snap.value!["mobile"] as! String!,
email: snap.value!["email"] as! String!,
password: "",
bio: snap.value!["bio"] as! String!,
profilePic: downloadedImg!,
openingHour: snap.value!["openingHour"] as! String!,
closingHour: snap.value!["closingHour"] as! String!)
newProducer = someProducer
print(newProducer?.description)
}) { (error) in
print(error.localizedDescription)
}
return newProducer!
}
正如我所说,我不知道何时,何地以及如何调用这些函数(在我的Feed控制器中)使其“同步”并将所有数据都提供给tableview Cells。我将感激你的每一个帮助。我尝试谷歌,甚至在这里找到它,但没有任何帮助我。
一旦你创建了所有的salePosts
,你应该打电话给tableView.reloadData()
。因此,在您循环创建将newSalePost
附加到salePosts
的位置之后。由于这是一个异步调用,因此在函数结束时返回salePosts是没用的。
我假设你有一个viewController的属性tableView
,你设置你的delegate
的datasource
和tableView
是你的viewController
。
别忘了在主线程上调用tableView.reloadData()
。
例如:Dispatch.main.async { self.tableView.reloadData() }
。
对于将来看到此帖子的用户,您还可以使用Dispatch组来处理从Firebase获取数据的异步属性。有关调度组工作的更多信息,请阅读Dispatch Groups in Swift 3。 Swift 4中的语法或多或少相同。这就是我用tableview为我的项目实现调度的方法。
var anEmptyArray: [String] = []
var dbRef: DatabaseReference!
@IBOutlet weak var myTable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
retrieveDataFromDatabase()
}
func retrieveDataFromDatabase() {
dbRef = Database.database().reference().child("user")
dbRef.observe(.value, with: { snapshot in
let group = DispatchGroup()
let enumerator = snapshot.children
while let rest = enumerator.nextObject() as? DataSnapshot {
group.enter()
self.categories.append(rest.value as! String)
group.leave()
}
group.notify(queue: .main) {
self.categoryTable.reloadData()
}
})
}
我使用了snapshot.children,因为我的数据结构如何。如何获取快照取决于您拥有的结构。调度组必须在dbRef.observe
关闭内使用。