UISearchBar:传递数据;单击的标题与 ListViewController - Swift 中显示的数据不对应
Posted
技术标签:
【中文标题】UISearchBar:传递数据;单击的标题与 ListViewController - Swift 中显示的数据不对应【英文标题】:UISearchBar: passing data; Title that is clicked on does not correspond with data that is shown in ListViewController - Swift 【发布时间】:2020-10-17 21:09:33 【问题描述】:我的 UISearchBar 目前有问题。因此,当我搜索一个单词时,UISearchBar 返回与我输入的字母/单词匹配的数据。但是,当我单击其中一个 tableview 单元格时,(标题)数据与 ListViewController 中显示的(项目)数据不对应。它所显示的(在 ListViewController 中)是与 tableView 的原始顺序/布局(索引)相对应的(项目)数据。因此,在搜索后,如果我单击与我搜索的内容匹配的第一个 tableView 单元格的(标题),它会显示(titledata)数组中第一个(字符串)的(项目)数据,而不是对应于标题显示。
例如: 如果我在我的 SearchBar New Haven(索引 1)和 New York(索引 2)中输入“New”。但是,当我单击(标题)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,000","University: Columbia University",]),
Category(title: "San Fransisco", items: ["Ann Arbor is a city located in Michigan.", "Population: 881,000","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 委托。
UISearchBar 代码:
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 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
【问题讨论】:
【参考方案1】:首先将数据源数组声明为非可选的空数组。
编辑:您的数据源应该是[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
,它会在数据源数组更改时为表格视图设置动画
【讨论】:
您好,感谢您的回复。现在我已将 let category = data[indexPath.row] 更改为: let category = filteredData[indexPath.row] 我收到错误消息,“让 vc 上的“'String' 类型的值没有成员 'items'” = ListViewController(items: category.items)" 代码行(在 didSelectRowAt 函数中)。再次感谢。 您的设计令人困惑。如果您需要类别,您的数据源数组必须是var filteredData = [Category]()
您好,再次感谢您的回复。我已经尝试进行上面的编辑,现在我在 3 行代码中遇到了同样的错误:“无法将类型 '[String]' 的值分配给类型 '[Category]'(注意:我已经将我的 searchBar 配置更改为您的)。我的应用程序的整个目标是在 tableView 中显示(标题)数据,并能够单击 tableView 单元格并让它在我设置的 ListViewController 中显示(项目)数据. 如果有更有效的方法来做到这一点,我很乐意适应。谢谢!
嗨 vadian,非常感谢您在这里与我合作。我已经进行了这些编辑,现在在 searchBar 配置中收到以下错误:无法推断成员'caseInsensitive'的上下文基础&'Category'类型的值没有成员'range'
两个错误都在以下代码行中:filteredData = data.filter$0.range(of searchText, options: .caseInsensitive) !=nil 【参考方案2】:
问题在于您的方法didSelectRowAt
,您正在使用filteredData
数组来显示项目,但是当您在单元格上执行点击时,您使用的是不同的数组:
let category = data[indexPath.row]
当您在单元格上执行点击时,您还需要使用过滤数组:
let category = filteredData[indexPath.row]
【讨论】:
如上所述,现在我已将 let category = data[indexPath.row] 更改为:let category = filteredData[indexPath.row] 我收到错误消息“'String' 类型的值在“let vc = ListViewController(items: category.items)”代码行(在 didSelectRowAt 函数中)没有成员“项目”。谢谢!以上是关于UISearchBar:传递数据;单击的标题与 ListViewController - Swift 中显示的数据不对应的主要内容,如果未能解决你的问题,请参考以下文章
单击 UISearchBar 的取消按钮后,如何使用 UISearchBar 刷新我的 UITableView?
NavigationItem + UISearchBar 与 Swift
当我在 NavigationBar 中单击 UISearchBar 时没有任何反应
iPhone UITableView 与 UISearchBar 和刷新部分索引