Reputation: 87
I'm trying to pass data onto my tableview, from my cloud firestore but it just not able to retrieve the data and post it on the tableview and so far most of of my attempts have failed. since I'm transition from real-time database to Firestore.
I've used multiple resources on stack, restructured my code multiple times and have now come down to this
here is also an image of my collection in Firestore firestore collection
import Foundation
class ProductList {
var id: String?
var name: String?
var dispensaryName: String?
var category: String?,
var brand: String?
var imageUrl: String?
init(id: String?,
name: String?,
dispensaryName: String?,
brand: String?,
category: String?,
imageUrl: String?) {
self.id = id
self.name = name
self.dispensaryName = dispensaryName
self.brand = brand
self.category = category,
self.imageUrl = imageUrl
}
}
import UIKit
class ProductListCell: UITableViewCell {
@IBOutlet weak var productImage: UIImageView!
@IBOutlet weak var dispensaryName: UILabel!
@IBOutlet weak var productName: UILabel!
@IBOutlet weak var categoryLabel: UILabel!
@IBOutlet weak var categoryStrain: UILabel!
}
import UIKit
import Firebase
import FirebaseFireStore
class ProductListController: UIViewController {
@IBOutlet weak var productListTableView: UITableView!
@IBOutlet weak var menuButton: UIBarButtonItem!
var dbRef: DatabaseReference!
var productSetup: [ProductList] = []
override func viewDidLoad() {
super.viewDidLoad()
productListTableView.dataSource = self
productListTableView.delegate = self
self.productListTableView.rowHeight = UITableView.automaticDimension
self.productListTableView.estimatedRowHeight = 363
menuButton.target = self.revealViewController()
menuButton.action = #selector(SWRevealViewController.revealToggle(_:))
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
dbRef = Database.database().reference().child("products");
//observing the data changes
dbRef.observe(DataEventType.value, with: { (snapshot) in
//if the reference have some values
if snapshot.childrenCount > 0 {
//clearing the list
self.productSetup.removeAll()
//iterating through all the values
for producting in snapshot.children.allObjects as! [DataSnapshot] {
//getting values
let productObject = producting.value as? [String: AnyObject]
let id = productObject?["id"]
let name = productObject?["name"]
let dispensaryName = productObject?["dispensaryName"]
let category = productObject?["category"]
let strain = productObject?["strain"]
let imageUrl = productObject?["imageUrl"]
//creating artist object with model and fetched values
let massProducts = ProductList(id: id as! String?,
name: name as! String?,
dispensaryName: dispensaryName as! String?,
category: category as! String?,
strain: strain as! String?,
imageUrl: imageUrl as! String?)
//appending it to list
self.productSetup.append(massProducts)
}
//reloading the tableview
print(self.productSetup)
self.productListTableView.reloadData()
}
})
}
}
extension ProductListController: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return productSetup.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ProductListCell") as!
ProductListCell
let production: ProductList
production = productSetup[indexPath.row]
cell.productName.text = "\(String(describing: production.brand)): \(String(describing: production.name))"
cell.dispensaryName.text = production.dispensaryName
cell.categoryLabel.text = production.category
cell.productImage.text = production.imageUrl
return cell
}
}
Upvotes: 1
Views: 442
Reputation: 153
I have reformatted the code quickly to make it easier to understand but it could be one of many things;
Reformatted Code
ProductListController.swift
import Firebase
class ProductListController: UIViewController {
@IBOutlet weak var productListTableView: UITableView!
@IBOutlet weak var menuButton: UIBarButtonItem!
var productSetup = [ProductList]()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
override func viewDidLoad() {
super.viewDidLoad()
productListTableView.dataSource = self
productListTableView.delegate = self
productListTableView.rowHeight = UITableView.automaticDimension
productListTableView.estimatedRowHeight = 363
menuButton.target = self.revealViewController()
menuButton.action = #selector(SWRevealViewController.revealToggle(_:))
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
fetchProducts { (products) in
self.productSetup = products
self.productListTableView.reloadData()
}
}
func fetchProducts(_ completion: @escaping ([ProductList]) -> Void) {
let ref = Firestore.firestore().collection("products")
ref.addSnapshotListener { (snapshot, error) in
guard error == nil, let snapshot = snapshot, !snapshot.isEmpty else {
return
}
completion(snapshot.documents.compactMap( {ProductList(dictionary: $0.data())} ))
}
}
}
extension ProductListController: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return productSetup.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "ProductListCell") as?
ProductListCell else { return UITableViewCell() }
cell.configure(withProduct: productSetup[indexPath.row])
return cell
}
}
ProductListCell.swift
import Firebase
class ProductListCell: UITableViewCell {
@IBOutlet weak var productImage: UIImageView!
@IBOutlet weak var dispensaryName: UILabel!
@IBOutlet weak var productName: UILabel!
@IBOutlet weak var categoryLabel: UILabel!
@IBOutlet weak var categoryStrain: UILabel!
func configure(withProduct product: ProductList) {
productName.text = "\(String(describing: product.brand)): \(String(describing: product.name))"
dispensaryName.text = product.dispensaryName
categoryLabel.text = product.category
fetchImage(withURL: product.imageUrl ) { (image) in
productImage.image = image
}
}
func fetchImage(withURL url: String, _ completion: @escaping (UIImage) -> Void) {
let ref = Storage.storage().reference(forURL: url)
ref.getData(maxSize: 1 * 1024 * 1024) { (data, error) in
guard error == nil, let imageData = data, let image = UIImage(data: imageData) else {
return
}
completion(image)
}
}
}
ProductList.swift
class ProductList {
var id: String
var name: String
var dispensaryName: String
var category: String
var brand: String
var imageUrl: String
init(id: String, name: String, dispensaryName: String, brand: String, category: String, imageUrl: String) {
self.id = id
self.name = name
self.dispensaryName = dispensaryName
self.brand = brand
self.category = category
self.imageUrl = imageUrl
}
convenience init(dictionary: [String : Any]) {
let id = dictionary["id"] as? String ?? ""
let name = dictionary["name"] as? String ?? ""
let dispensaryName = dictionary["dispensaryName"] as? String ?? ""
let brand = dictionary["brand"] as? String ?? ""
let category = dictionary["category"] as? String ?? ""
let imageUrl = dictionary["imageUrl"] as? String ?? ""
self.init(id: id, name: name, dispensaryName: dispensaryName, brand: brand, category: category, imageUrl: imageUrl)
}
}
I Hope you found this helpful.
Upvotes: 1