UISearchBar для фильтрации пользовательских UITableViewCells - PullRequest
0 голосов
/ 21 апреля 2020

Я пытаюсь отфильтровать пользовательские UITableViewCells на основе одного из UILabels, присутствующих в ячейке.

Все данные анализируются с удаленного 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()
    }

Заранее благодарен за любую помощь здесь.

Ответы [ 2 ]

1 голос
/ 21 апреля 2020

Вы не можете фильтровать 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()
            }
        }
0 голосов
/ 21 апреля 2020

Вы делаете это неправильно.

  1. Вы не должны фильтровать ячейки , а вместо этого фильтровать модель (например, добавлять и удалять записи к источнику данных табличного представления)
  2. Затем вызовите reloadData - это откроет доступ к отфильтрованной модели (в cellForRowAt и создаст только отфильтрованное количество (видимых) ячеек
  3. Для улучшения , используйте диффузный источник данных
...