如何使用委托过滤具有多个按钮的数据?
Posted
技术标签:
【中文标题】如何使用委托过滤具有多个按钮的数据?【英文标题】:how to filter data with multiple buttons using delegate? 【发布时间】:2020-01-09 13:50:41 【问题描述】:我正在使用的Delegate用于在FilterVC中按下按钮时使用委托过滤掉指定的类别
我正在苦苦挣扎的是在 FilterVC 中设置按钮,以便过滤器在 HomeVC 中工作
我注意到,当我在 @IBAction func acceptSelections
中使用委托时,我的 FilterVC 可能出现问题,我收到错误无法转换类型“RoundButton?”的值到预期的参数类型“字符串?”当使用delegate控制哪个类别时调用按钮时
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)
【问题讨论】:
您将方法签名定义为期望可选字符串,但您正在传递按钮对象 建议:少用“控制器”这个词有助于提高可读性。 圣地亚哥小姐,为什么要将整个视图控制器(FilterViewController)发送给 HomeViewController?没有意义。 【参考方案1】:由于过滤器功能是纯布尔值,我建议只返回按钮的 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)
这似乎是一个多项选择,因此您必须在查询中组合选项。
【讨论】:
它可以工作,但现在我在我的extension HomeViewController: FiltersViewControllerDelegate
中遇到各种错误,同样的错误是条件绑定的初始化程序必须具有可选类型,而不是“布尔”,我在每一个if 语句
当然可以,类型已更改,所有值都是非可选的,因此您可以摆脱可选绑定。你必须调整方法。以上是关于如何使用委托过滤具有多个按钮的数据?的主要内容,如果未能解决你的问题,请参考以下文章
如何在具有 Ajax 的单个表单中使用多个提交按钮 [关闭]
如何在 octobercms 中过滤具有多个类别的博客文章?