UISearchBar 过滤自定义 UITableViewCells
UISearchBar to filter custom UITableViewCells
我正在尝试根据单元格中存在的 UILabel 之一过滤自定义 UITableViewCells。
所有数据都是从远程 JSON 解析的,它的本地模型名为 Item
,目前我在每个单元格中成功显示以下内容:
var titleLabel = UILabel()
var descriptionLabel = UILabel()
我的ItemTableViewCell
中也定义了class是:
func set(product: Item) {
DispatchQueue.main.async { [weak self] in
self?.titleLabel.text = item.title
self?.descriptionLabel.text = item.listPrice
}
}
这些是在我的主视图控制器中调用的,我已成功向其添加了一个搜索栏,并且在应用程序中可见:
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
}
}
我如何过滤这些单元格,例如用户搜索 "Food",唯一 return 的项目是具有单元格 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()
}
在此先感谢您的帮助。
你做错了。
- 您不应过滤 单元格 ,而应过滤 模型 (例如,向 table 添加和删除条目查看数据源)
- 然后调用
reloadData
- 然后这将访问过滤模型(在 cellForRowAt
中并仅创建过滤数量的(可见)单元格
- 要改进,请使用可区分数据源
您不能筛选 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()
}
}
我正在尝试根据单元格中存在的 UILabel 之一过滤自定义 UITableViewCells。
所有数据都是从远程 JSON 解析的,它的本地模型名为 Item
,目前我在每个单元格中成功显示以下内容:
var titleLabel = UILabel()
var descriptionLabel = UILabel()
我的ItemTableViewCell
中也定义了class是:
func set(product: Item) {
DispatchQueue.main.async { [weak self] in
self?.titleLabel.text = item.title
self?.descriptionLabel.text = item.listPrice
}
}
这些是在我的主视图控制器中调用的,我已成功向其添加了一个搜索栏,并且在应用程序中可见:
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
}
}
我如何过滤这些单元格,例如用户搜索 "Food",唯一 return 的项目是具有单元格 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()
}
在此先感谢您的帮助。
你做错了。
- 您不应过滤 单元格 ,而应过滤 模型 (例如,向 table 添加和删除条目查看数据源)
- 然后调用
reloadData
- 然后这将访问过滤模型(在cellForRowAt
中并仅创建过滤数量的(可见)单元格 - 要改进,请使用可区分数据源
您不能筛选 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()
}
}