简体   繁体   中英

how do I fetch data from the Firestore?

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
      }
  }

I have reformatted the code quickly to make it easier to understand but it could be one of many things;

  1. Check user authenticated with firebase on the device.
  2. Ensure you have setup security settings correctly to allow reads in firebase.

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.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM