Как отфильтровать данные с помощью нескольких кнопок с помощью делегата? - PullRequest
0 голосов
/ 09 января 2020

Используемый мной делегат используется для фильтрации указанной категории с использованием делегата при нажатии кнопки в FilterV C

, с чем я сталкиваюсь, это настройка кнопок в FilterV * 1016. * так что фильтр работает в HomeV C

я заметил, что проблема может быть в моем FilterV C при использовании делегата в @IBAction func acceptSelections, где я получаю ошибку Не удается преобразовать значение типа 'RoundButton ? к ожидаемому типу аргумента 'String?' при вызове кнопок при использовании делегата для управления категорией

screens

import UIKit
import Firebase
import FirebaseFirestore

class HomeViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!

    @IBOutlet var activeFiltersStackView: UIStackView!
    @IBOutlet var stackViewHeightConstraint: NSLayoutConstraint!
    @IBOutlet var jewelryFilterLbl: UILabel!
    @IBOutlet var hatFilterLbl: UILabel!   
    @IBOutlet var shoeFilterLbl: UILabel!
    @IBOutlet var apparelFilterLbl: UILabel!
    @IBOutlet var gearFilterLbl: UILabel!

    private lazy var baseQuery: Query = {
      return Firestore.firestore().collection("products").limit(to: 50)
    }()

    fileprivate var query: Query?

    lazy private var filters: (navigationController: UINavigationController,
                           filtersController: FilterViewController) = {
          return FilterViewController.fromStoryboard(delegate: self)
    }()

    @IBAction func didTapClearBtn(_ sender: Any){
        filters.filtersController.clearFilters()
        controller(filters.filtersController, didSelectCategory: nil, sativa: nil, indica: nil, hybrid: nil, gear: nil)
    }

    var productSetup: [ProductList] = []
    var products: ProductList?

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.dataSource = self
        tableView.delegate = self

        // arranges products by store nearest you
        fetchProducts { (products) in
            self.productSetup = products.sorted(by: { $0.itemName < $1.itemName })
            self.productListTableView.reloadData()
        }
    }

    // fetches Firebase Data
    func fetchProducts(_ completion: @escaping ([ProductList]) -> Void) {
        let productQuery = Firestore.firestore().collection("products").limit(to: 50)
        productQuery.addSnapshotListener { (snapshot, error) in
            guard error == nil, let snapshot = snapshot, !snapshot.isEmpty else {
                return
            }
            completion(snapshot.documents.compactMap( {ProductList(dictionary: $0.data())} ))
        }
        // shows Firestore data in log (not neccessary code just used to be seen in logs)
        productQuery.getDocuments { (snapshot, error) in
            if let error = error {
                print("Oh no! Got an error! \(error.localizedDescription)")
                return
            }
            guard let snapshot = snapshot else { return }
            let allDocuments = snapshot.documents
            for productDocument in allDocuments {
                print("I have this product \(productDocument.data())")
            }
        }
    }
}

extension HomeViewController: 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: "HomeCell") as?
        HomeCell else { return UITableViewCell() }

        cell.configure(withProduct: productSetup[indexPath.row])

        return cell
    }

}

extension HomeViewController: FiltersViewControllerDelegate{
    func query(withCategory jewelry: String?, hat: String?, shoe: String?, gear: String?, apparel: String?) -> Query {

      if jewelry == nil && hat == nil && shoe == nil && gear == nil && apparel == nil {
          stackViewHeightConstraint.constant = 0
          activeFiltersStackView.isHidden = true
      } else {
          stackViewHeightConstraint.constant = 44
          activeFiltersStackView.isHidden = false
      }

      var filtered = baseQuery

      // Sort and Filter data

      if let jewelry = jewelry, !jewelry.isEmpty {
          filtered = filtered.whereField("category", isEqualTo: jewelry)
      }

      if let hat = hat, ! hat.isEmpty {
          filtered = filtered.whereField("category", isEqualTo: hat)
      }

      if let shoe = shoe, !shoe.isEmpty {
          filtered = filtered.whereField("category", isEqualTo: shoe)
      }

      if let gear = gear, !gear.isEmpty {
          filtered = filtered.whereField("category", isEqualTo: gear)
      }

      if let apparel = apparel, !apparel.isEmpty {
          filtered = filtered.whereField("category", isEqualTo: apparel)
      }

      return filtered
  }

  func controller(_ controller: FilterViewController,
                  didSelectCategory jewelry: String?,
                  hat: String?,
                  shoe: String?,
                  gear: String?,
                  apparel: String?) {

        if jewelry == nil && hat == nil && shoe == nil && gear == nil && apparel == nil {
            stackViewHeightConstraint.constant = 0
            activeFiltersStackView.isHidden = true
        } else {
            stackViewHeightConstraint.constant = 44
            activeFiltersStackView.isHidden = false
        }

        let filtered = query(withCategory: jewelry, hat: hat, shoe: shoe, gear: gear, apparel: apparel)

        if let jewelry = jewelry, ! jewelry.isEmpty {
            jewelryFilterLbl.text = jewelry
            jewelryFilterLbl.isHidden = false
        } else {
            jewelryFilterLbl.isHidden = true
        }

        if let hat = hat, ! hat.isEmpty {
            hatFilterLbl.text = hat
            hatFilterLbl.isHidden = false
        } else {
            hatFilterLbl.isHidden = true
        }

        if let shoe = shoe, ! shoe.isEmpty {
            shoeFilterLbl.text = shoe
            shoeFilterLbl.isHidden = false
        } else {
            shoeFilterLbl.isHidden = true
        }

        if let gear = gear, !gear.isEmpty {
            gearFilterLbl.text = gear
            gearFilterLbl.isHidden = false
        } else {
            gearFilterLbl.isHidden = true
        }

        if let apparel = apparel, ! apparel.isEmpty {
            apparelFilterLbl.text = apparel
            apparelFilterLbl.isHidden = false
        } else {
            apparelFilterLbl.isHidden = true
        }

        query = filtered
    }

}

import UIKit
import Firebase

protocol FiltersViewControllerDelegate: NSObjectProtocol {
  func controller(_ controller: FilterViewController,
                  didSelectCategory jewelry: String?,
                  hat: String?,
                  shoe: String?,
                  gear: String?,
                  apparel: String?)
}

class FilterViewController: UIViewController {

    @IBOutlet weak var jewelryBtn: RoundButton!
    @IBOutlet weak var hatBtn: RoundButton!
    @IBOutlet weak var shoeBtn: RoundButton!
    @IBOutlet weak var gearBtn: RoundButton!
    @IBOutlet weak var apparelBtn: RoundButton!

    static func fromStoryboard(delegate: FiltersViewControllerDelegate? = nil) ->
    (navigationController: UINavigationController, filtersController: FilterViewController) {
      let navController = UIStoryboard(name: "Main", bundle: nil)
          .instantiateViewController(withIdentifier: "FiltersViewController")
      as! UINavigationController
      let controller = navController.viewControllers[0] as! FilterViewController
      controller.delegate = delegate
      return (navigationController: navController, filtersController: controller)
    }

    weak var delegate: FiltersViewControllerDelegate?

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    @IBAction func filterSelect(_ sender: Any) {
        if let button : UIButton = sender as? UIButton
        {
            button.isSelected = !button.isSelected

            if (button.isSelected)
            {
                button.backgroundColor = .green
            }
            else
            {
                button.backgroundColor = .gray
            }
        }
    }

    func clearFilters() {
        apparelBtn.isSelected = false
        jewelryBtn.isSelected = false
        shoeBtn.isSelected = false
        hatBtn.isSelected = false
        gearBtn.isSelected = false
    }

    @IBAction func closeFilter(_ sender: Any) {
        dismiss(animated: true, completion: nil)
    }

    @IBAction func acceptSelections(_ sender: Any) {
        delegate?.controller(self,                          //Problem integrating the buttons to get the correct category
                             didSelectCategory: jewelryBtn,
                             hat: hatBtn,
                             shoe: shoeBtn,
                             gear: gearBtn,
                             apparel: apparelBtn)
        dismiss(animated: true)
    }
}

1 Ответ

3 голосов
/ 09 января 2020

Поскольку функциональность фильтра чисто логическая, я рекомендую просто вернуть isSelected значения кнопок

protocol FiltersViewControllerDelegate: NSObjectProtocol {
  func controller(_ controller: FilterViewController,
                  didSelectCategory jewelry: Bool,
                  hat: Bool,
                  shoe: Bool,
                  gear: Bool,
                  apparel: Bool)
}

и назвать его

@IBAction func acceptSelections(_ sender: Any) {
    delegate?.controller(self,
                         didSelectCategory: jewelryBtn.isSelected,
                         hat: hatBtn.isSelected,
                         shoe: shoeBtn.isSelected,
                         gear: gearBtn.isSelected,
                         apparel: apparelBtn.isSelected)
    dismiss(animated: true)
}

Кажется, это кратно выбор выбора, поэтому вы должны объединить параметры в запросе.

...