UISearchBar:传递数据;单击的标题与 ListViewController 中显示的数据不对应 - Swift

UISearchBar: passing data; Title that is clicked on does not correspond with data that is shown in ListViewController - Swift

我目前的 UISearchBar 有问题。因此,当我搜索一个词时,UISearchBar returns 匹配我输入的字母/词的数据。但是,当我单击其中一个表格视图单元格时,(标题)数据与 ListViewController 中显示的(项目)数据不对应。它显示的是(在 ListViewController 中)与 tableView 的原始 order/layout(索引)相对应的(项目)数据。因此,在搜索后,如果我单击与我搜索的内容匹配的第一个 tableView 单元格的 (title),它会显示 (titledata) 数组中第一个 (string) 的 (items) 数据,而不是对应于标题显示。

例如: 如果我在我的 SearchBar New Haven(索引 1)和 New York(索引 2)中键入“New”弹出。但是,当我单击(标题)New Haven tableView 单元格时,它会将我带到 Ann Arbor 的(项目)数据(原始布局的第一个索引)

谢谢!

结构代码:

struct Category {
   let title: String
   let items: [String]
}

数据(数组:从结构派生)代码:

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"]

过滤数据变量:

 var filteredData: [String]!

在 viewDidLoad 函数中:

filteredData = titledata

注意:在 Storyboard 中链接了 SearchBar Delegate。

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
}

问题出在您的方法 didSelectRowAt 中,您正在使用 filteredData 数组来显示项目,但是当您在单元格上执行点击时,您使用的是不同的数组:

let category = data[indexPath.row]

当您在单元格上执行点击时,您也需要使用过滤数组:

let category = filteredData[indexPath.row]

首先声明一个数据源数组总是non-optional空数组。

编辑:您的数据源应该是[Category]而不是[String]

var filteredData = [Category]()

viewDidLoad赋值data中,不需要titledata数组。删除它。

filteredData = data

由于 filteredData 是数据源数组,您必须从 didSelectRowAt

中的此数组中获取项目
let category = filteredData[indexPath.row]

还有一些可以优化的东西。 在 textDidChange 中,过滤数据的方式非常昂贵,因为存在循环,而且更糟糕的是,在每次迭代中都会重新加载 table 视图。

这样效率更高

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    if searchText.isEmpty {
        filteredData = data
    } else {
        filteredData = data.filter{[=13=].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,它会在数据源数组更改时为 table 视图设置动画