搜索栏筛选器不适用于我的数组项



我有一些数组,其中包含标题、说明/注释和runDate。这张表运行得很好,但现在我正在添加一个搜索栏。然而,过滤器没有拾取任何东西——它没有提供任何弹出选项。故障线:

searchingRuns = runs.filter({$0.title.lowercased().prefix(searchText.count) == searchText.lowercased()})

这是因为我需要调用数组项而不仅仅是数组,例如:runs.title.filter…我确实尝试过,但没有成功。

import UIKit
class RunTableViewController: UITableViewController, RunCellDelegate, UISearchBarDelegate {

var runs = [Run]()

@IBOutlet weak var searchBar: UISearchBar!

var searchingRuns = [String]()
var searching = false

override func viewWillAppear(_ animated: Bool) {
if let savedRuns = Run.loadRuns() {
runs = savedRuns
}

runs.sort { $0.runDate > $1.runDate}
tableView.reloadData()
}

override func viewDidLoad() {
super.viewDidLoad()

navigationItem.leftBarButtonItem = editButtonItem

if let savedRuns = Run.loadRuns() {
runs = savedRuns
}

runs.sort { $0.runDate > $1.runDate}
tableView.reloadData()
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searching {
return searchingRuns.count
} else {
return runs.count
}
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "RunCellIdentifier") as? RunCell else {
fatalError("Could not dequeue a cell")
}
if searching {
cell.textLabel?.text = searchingRuns[indexPath.row]
} else {

cell.delegate = self

let run = runs[indexPath.row]
cell.titleLabel?.text = run.title
cell.descriptionLabel.text = run.notes
cell.dateLabel.text = Run.runDateFormatter.string(from: run.runDate)
}

return cell
}

override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {

runs.sort { $0.runDate > $1.runDate}

return true
}

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
runs.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
Run.saveRuns(runs)
}
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showDetails" {
let runViewController = segue.destination as! RunViewController
let indexPath = tableView.indexPathForSelectedRow!
let selectedRun = runs[indexPath.row]
runViewController.run = selectedRun
}
}

@IBAction func unwindToRunList(segue: UIStoryboardSegue) {
guard segue.identifier == "saveUnwind" else { return }
let sourceViewController = segue.source as! RunViewController

if let run = sourceViewController.run {
if let selectedIndexPath = tableView.indexPathForSelectedRow {
runs[selectedIndexPath.row] = run
tableView.reloadRows(at: [selectedIndexPath], with: .none)
} else {
let newIndexPath = IndexPath(row: runs.count, section: 0)
runs.append(run)
tableView.insertRows(at: [newIndexPath], with: .automatic)
}
}

Run.saveRuns(runs)

if let savedRuns = Run.loadRuns() {
runs = savedRuns
}

runs.sort { $0.runDate > $1.runDate}
tableView.reloadData()
}

func checkmarkTapped(sender: RunCell) {
if let indexPath = tableView.indexPath(for: sender) {
let run = runs[indexPath.row]
runs[indexPath.row] = run
tableView.reloadRows(at: [indexPath], with: .automatic)
Run.saveRuns(runs)
}
}

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
searchingRuns = runs.filter({$0.title.lowercased().prefix(searchText.count) == searchText.lowercased()})
searching = true
tableView.reloadData()
}

func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searching = false
searchBar.text = ""
tableView.reloadData()
}
}

您的代码中存在一些问题:

viewWillAppear/viewDidLoad

您正在两种方法中加载运行,这是多余的。您不需要在viewDidLoad中执行此操作,因为viewWillAppear将在viewDidRoad之后立即调用。

tableView(_:canEditRowAt:(在这里,为什么要重新对跑步进行排序?拆下那根线。记住:每当您更改数据源(添加、删除、更改顺序(时,您还需要更新表视图

筛选
您的代码中有一堆if searching ...语句,很难维护,而且您已经可以看到在各种方法中都缺少它。

最好的方法是——就像@ElTomato所写的那样——有两个独立的数组,其中一个包含";原始的";数据,以及一个保存";过滤的";数据

  • 在您的代码中,您几乎总是使用过滤后的数据
  • 在重新加载、筛选或取消筛选时,可以从原始数据中重新创建筛选后的数据。如果不进行筛选,则它们是相同的
  • 修改时,修改原始数据,然后重新创建筛选后的数据

最新更新