i have a FireBase database, inside i have a table of products and another table of orders with ids of these products, what i am trying to do is to get products from table of products based on ids inside table of orders, since FireBase will only allow me to get the products one by one, my tableview is loaded before i get all products that are referenced inside the orders table.
heres how i did that:
struct Product: Decodable, Encodable{
var id: String?
var ref: String
var description: String
var type: String
var price: String
var qtyOrdred:Int?
}
struct Order:Decodable, Encodable {
var id: String?
var isValide: Bool
var madeBy: String
var info: String?
var ordredProd: [OrderedProduct]
}
struct OrderedProduct:Decodable, Encodable {
var id: String
var qty: Int
}
func getData(completion: @escaping ([Product])->Void){
var allProduct = [Product]()
for product in orderedProduct {
getProductWithKey(qty: product.qty, key: product.id) { (p) in
print(p.ref)
allProduct.append(p)
}
}
}
func getProductWithKey(qty: Int,key: String, completion: @escaping (Product)->Void) {
Database.database().reference().child("products").child(key).observeSingleEvent(of: .value) { (snap) in
if let productObject = snap.value as? [String: Any]
{
if let ref = productObject["ref"],
let price = productObject["price"],
let type = productObject["type"],
let description = productObject["description"],
let id = productObject["id"]{
let p = Product(id: id as? String, ref: ref as! String, description: description as! String, type: type as! String, price: price as! String, qtyOrdred: qty)
completion(p)
}
}
}
}
i call it like this:
override func viewWillAppear(_ animated: Bool) {
self.getData { (ps) in
print(ps)
self.tableView.reloadData()
}
}
The problem is that it always print an empty array, and my tableview data never changes
You don't return from getData
completion, you need a dispatch group
let g = DispatchGroup()
func getData(completion: @escaping ([Product])->Void){
var allProduct = [Product]()
for product in orderedProduct {
g.enter()
getProductWithKey(qty: product.qty, key: product.id) { (p) in
print(p.ref)
allProduct.append(p)
g.leave()
}
}
g.notify(queue:.main) {
completion(allProduct)
}
}
Your getData function is returning as soon as the for loop is finished. As the call inside the loop is async there isn't any data when the loop finishes.
Instead of reloading the table just insert rows as they arrive.
for product in orderedProduct {
getProductWithKey(qty: product.qty, key: product.id) { [weak self] (p) in
guard let self = self else { return }
allProduct.append(p)
guard let index = allProduct.firstIndex(of: p) else { return }
self.tableView.insertRow(at: IndexPath(row: index, section: 0))
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.