【问题标题】:UISearchBar to filter custom UITableViewCellsUISearchBar 过滤自定义 UITableViewCells
【发布时间】:2020-08-04 11:05:21
【问题描述】:

我正在尝试根据单元格中存在的 UILabel 之一过滤自定义 UITableViewCells。

所有数据都是从远程 JSON 中解析出来的,它的模型在本地命名为 Item,目前我在每个单元格中成功显示以下内容:

var titleLabel = UILabel()
var descriptionLabel = UILabel()

在我的ItemTableViewCell 类中也定义了:

  func set(product: Item) {
        DispatchQueue.main.async { [weak self] in
            self?.titleLabel.text = item.title
            self?.descriptionLabel.text = item.listPrice
        }
    }

这些是在我的主视图控制器中调用的,我已成功向其中添加了一个 searchBar 并且在应用程序中可见:

import Foundation
import UIKit

class ItemsListViewController: UIViewController {

    var items = [Items]()
    var itemsSearch: [Items] = []
    var tableView = UITableView()
    var searchController = UISearchController()

    struct Cells {
        static let itemCell = "ItemCell"
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        configureTableView()
        configureSearchController()
    }

    func configureSearchController() {
        searchController = UISearchController(searchResultsController: nil)
        navigationItem.searchController = searchController
        navigationItem.hidesSearchBarWhenScrolling = false
        searchController.searchBar.placeholder = "Search items"
        definesPresentationContext = true
        var isSearchBarEmpty: Bool {
          return searchController.searchBar.text?.isEmpty ?? true
        }
    }

    func configureTableView() {
        view.addSubview(tableView)
        setTableViewDelegates()
        tableView.rowHeight = 100
        tableView.pin(to: view)
        tableView.register(itemTableViewCell.self, forCellReuseIdentifier: Cells.itemCell)
    }

    func setTableViewDelegates() {
        tableView.delegate = self
        tableView.dataSource = self
    }
}

extension itemsListViewController: UITableViewDelegate, UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return items.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: Cells.itemCell) as! itemTableViewCell
        let item = items[indexPath.row]
        cell.set(item: item)
        return cell
    }
}

extension ItemsListViewController: UISearchResultsUpdating {
    func updateSearchResults(for searchController: UISearchController) {
        let searchBar = searchController.searchBar
  }
}

我如何过滤这些单元格,例如用户搜索“食物”,返回的唯一项目将是具有单元格 titleLabel = "food" 的项目?

我尝试实现类似于以下的功能,但是它无法实现我所追求的:

  func filterContentForSearchText(_ searchText: String, category:  = nil) {
    let cell = tableView.dequeueReusableCell(withIdentifier: Cells.productCell) as! ProductTableViewCell
      productsSearch = products.filter { (cell: cell) -> Bool in
        return products.name.lowercased().contains(searchText.lowercased())
      }
      tableView.reloadData()
    }

在此先感谢您的帮助。

【问题讨论】:

    标签: ios swift uitableview uisearchbar uisearchcontroller


    【解决方案1】:

    您不能过滤 TableViewCells。你必须过滤你的模型数据,而不是使用UISearchResultsUpdating,你应该使用UISearchBarDelegate

    我修改了你的代码,检查一下。

    class ItemsListViewController: UIViewController {
    
        var items = [Items]()
        var itemsSearch: [Items] = []
    
        var filterActive = false
        var tableView = UITableView()
        var searchController = UISearchController()
    
        struct Cells {
            static let itemCell = "ItemCell"
        }
    
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            configureTableView()
            configureSearchController()
        }
    
        func configureSearchController() {
            searchController = UISearchController(searchResultsController: nil)
            navigationItem.searchController = searchController
            navigationItem.hidesSearchBarWhenScrolling = false
            searchController.searchBar.placeholder = "Search items"
            searchController.searchBar.delegate = self
            definesPresentationContext = true
    
        }
    
        func configureTableView() {
            view.addSubview(tableView)
            setTableViewDelegates()
            tableView.rowHeight = 100
            tableView.pin(to: view)
            tableView.register(itemTableViewCell.self, forCellReuseIdentifier: Cells.itemCell)
        }
    
        func setTableViewDelegates() {
            tableView.delegate = self
            tableView.dataSource = self
        }
    }
    
    extension ItemsListViewController: UITableViewDelegate, UITableViewDataSource {
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return filterActive ? itemsSearch.count : items.count
        }
    
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: Cells.itemCell) as! itemTableViewCell
    
            let item = filterActive ?  itemsSearch[indexPath.row] : items[indexPath.row]
            cell.set(item: item)
            return cell
        }
    }
    
    extension ItemsListViewController: UISearchBarDelegate {
    
        func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String)  {
            filterItems(text: searchController.searchBar.text)
        }
        func filterItems(text: String?) {
            guard let text = text else {
                filterActive = false
                self.tableView.reloadData()
                return
            }
    
            self.itemsSearch = self.items.filter({ (item) -> Bool in
                    return item.title.lowercased().contains(text.lowercased())
            })
            filterActive = true
            self.tableView.reloadData()
        }
    
    // Edited Version 
    
    
         func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
                    searchBar.text = nil
                    filterActive = false
                    self.tableView.reloadData()
                }
            }
    

    【讨论】:

    • 我已将其标记为正确,因为它回答了我最初的问题 - 谢谢。跟进 Q,我如何清除搜索后显示的数据?我现在可以过滤项目了,但是 VC 的默认状态会停留在过滤的结果上,即使在取消搜索后也是如此
    • 实现 UISearchBarDelegate 的 searchBarCancelButtonClicked 方法,我也编辑了我的答案。
    • 这也有效!唯一的问题是如果我点击搜索然后立即点击取消然后没有列表加载
    • 是的,我明白了请像我一样实现 searchBarCancelButtonClicked 方法,当您点击 searchBar 取消按钮并重置 tableView 时它会调用
    【解决方案2】:

    你做错了。

    1. 您不应该过滤 cells,而应该过滤 model(例如,向表格视图数据源添加和删除条目)
    2. 然后调用 reloadData - 这将访问过滤后的模型(在 cellForRowAt 中并仅创建过滤后的(可见)单元格数量
    3. 要改进,请使用可区分的数据源

    【讨论】:

    • 您好,谢谢您的回答。我不认为我可以更改我的数据源,因为它来自无法在本地存储的远程 JSON
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-29
    • 1970-01-01
    • 2023-03-13
    • 2012-12-06
    • 1970-01-01
    相关资源
    最近更新 更多