问题描述
我的UISearchBar当前遇到问题。因此,当我搜索单词时,UISearchBar返回与我键入的字母/单词匹配的数据。但是,当我单击表视图单元格之一时,(标题)数据与ListViewController中显示的(项目)数据不对应。它所显示的(在ListViewController中)是与tableView的原始顺序/布局(索引)相对应的(项)数据。因此,在搜索是否单击了与我搜索的内容相匹配的第一个tableView单元格的(标题)之后,它在(titledata)数组中显示了第一个(字符串)的(项目)数据,而不是对应于显示。
例如: 如果我在SearchBar纽黑文(索引1)和纽约(索引2)中输入“新建”,则会弹出。但是,当我单击(标题)New Haven tableView单元格时,它将带我到Ann Arbor的(项目)数据(原始布局的第一个索引)
谢谢!
结构代码:
struct Category {
let title: String
let items: [String]
}
数据(数组:从Struct派生)代码:
let data: [Category] = [
Category(title: "Ann Arbor",items: ["Ann Arbor is a city located in Michigan.","Population: 119,000","University: University of Michigan is located in Ann Arbor.",]),Category(title: "Los Angeles",items: ["Los Angeles is a city located in California.","Population: 3,900,000,","University: University of California of Los Angeles",Category(title: "New Haven",items: ["New Haven is a city located in Connecticut.","Population: 130,000 ","University: Yale University",Category(title: "New York City",items: ["New York City is located in New York.","Population: 8,300,"University: Columbia University",Category(title: "San Fransisco","Population: 881,"University: University of San Francisco",]
titledata(数组)代码:
let titledata = ["Ann Arbor","Los Angeles","New Haven","New York City","San Fransisco"]
filteredData变量:
var filteredData: [String]!
在viewDidLoad函数中:
filteredData = titledata
注意:Storyboard中链接了SearchBar委托。
UISearch条形码:
func searchBar(_ searchBar: UISearchBar,textDidChange searchText: String) {
filteredData = []
if searchText == "" {
filteredData = titledata
}
else {
for info in titledata {
if info.lowercased().contains(searchText.lowercased()) {
self.tableView.reloadData()
filteredData.append(info)
self.tableView.reloadData()
}
}
}
self.tableView.reloadData()
}
didSelectRowAt Func:
func tableView(_ tableView: UITableView,didSelectRowAt indexPath: IndexPath) {
let category = data[indexPath.row]
let vc = ListViewController(items: category.items)
vc.title = category.title
self.navigationController?.pushViewController(vc,animated: true)
}
numberOfRowsInSection函数:
func tableView(_ tableView: UITableView,numberOfRowsInSection section: Int) -> Int {
return filteredData.count
}
cellForRowAt函数:
func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell",for: indexPath) as! MyTableViewCell
cell.myLabel.text = filteredData[indexPath.row]
cell.myImg.image = UIImage(named: filteredData[indexPath.row] + ".png")
return cell
}
解决方法
问题出在您的方法didSelectRowAt
中,您正在使用filteredData
数组显示项目,但是当执行单元格点击时,您正在使用其他数组:
let category = data[indexPath.row]
在执行单元格点击时,还需要使用过滤后的数组:
let category = filteredData[indexPath.row]
,
首先,将数据源数组始终声明为非可选的空数组。
编辑:您的数据源应该是[Category]
而不是[String]
var filteredData = [Category]()
在viewDidLoad
分配data
中,不需要titledata
数组。删除它。
filteredData = data
由于filteredData
是数据源数组,因此您必须从didSelectRowAt
的该数组中获取项目
let category = filteredData[indexPath.row]
还有其他一些可以优化的东西。
在textDidChange
中,由于存在循环,并且(更糟的是,每次迭代都重新加载表视图),因此过滤数据的方法非常昂贵。
效率更高
func searchBar(_ searchBar: UISearchBar,textDidChange searchText: String) {
if searchText.isEmpty {
filteredData = data
} else {
filteredData = data.filter{$0.title.range(of: searchText,options: .caseInsensitive) != nil }
}
self.tableView.reloadData()
}
并将cellForRowAt
替换为
func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell",for: indexPath) as! MyTableViewCell
let title = filteredData[indexPath.row].title
cell.myLabel.text = title
cell.myImg.image = UIImage(named: title + ".png")
return cell
}
如果您喜欢精美的动画,请使用UITableViewDiffableDataSource
,它会根据数据源数组的变化为表格视图添加动画