json - 如何使用 Swift 4.2 创建 searchBar 全局搜索可编码 JSON 数组值?
问题描述
我的场景,我在Codable 结构的帮助下加载JSON
数据。tableview
在这里,我尝试Searchbar
使用storyboard
. 我不知道如何self.tableArray
与搜索栏同步数据filtered array
。请提供一些想法。
MY 可编码结构
struct Root: Codable {
let data: [Datum]
}
struct Datum: Codable {
let id, userID, country, card: Int
let category: Int
let title, description: String
let createDate
let user: User
enum CodingKeys: String, CodingKey {
case id
case userID = "user_id"
case country, card, category, title, description
case createDate = "create_date"
}
}
struct User: Codable {
let firstname, lastname: String
}
我的 JSON 代码
do {
let result = try JSONDecoder().decode(Root.self, from:data!)
self.tableArray = result.data
} catch {
print(error)
self.tableArray = []
}
我的表格视图代码
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//return filteredData.count
return tableArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath) as! CustomTableViewCell
let item = tableArray[indexPath.row]
cell.name_label.text = ("\(item.user.firstname) " + "\(item.user.lastname)")
cell.date_label.text = item.createDate
return cell
}
搜索条码
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
// When there is no text, filteredData is the same as the original data
// When user has entered text into the search box
// Use the filter method to iterate over all items in the data array
// For each item, return true if the item should be included and false if the
// item should NOT be included
filteredData = searchText.isEmpty ? names : names.filter({(dataString: String) -> Bool in
// If dataItem matches the searchText, return true to include it
return dataString.range(of: searchText, options: .caseInsensitive) != nil
})
tableView.reloadData()
}
解决方案
首先需要委托搜索栏所以添加它UISearchBarDelegate
。在这种方法中,有一个功能可以检查搜索栏中的文本是否发生了变化。这是
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { }
但首先你需要声明一个变量。
var isSearching = false
并添加此功能
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchBar.text == nil || searchBar.text == "" { //
isSearching = false
view.endEditing(true)
tableView.reloadData()
}
else {
isSearching = true
newArray = tableArray.filter({ value -> Bool in
guard let text = searchBar.text else { return false}
return value.title.contains(text) // According to title from JSON
})
tableView.reloadData()
}
}
newArray 是同一个 tableArray 但它是空的。
您需要检查 als numberOfRowsInSection
。如果你不修改,它可能会给出错误,如Index of out of range
更改
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if isSearching {
return newArray.count
}
else {
return self.tableArray.count
}
return 0
}
更新
:我认为问题出在这部分。您还需要在isSearching
此处添加
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath) as! CustomTableViewCell
if isSearching{
// Need to change according to newArray
let item = newArray[indexPath.row]
cell.name_label.text = ("\(item.user.firstname) " + "\(item.user.lastname)")
cell.date_label.text = item.createDate
}
else {
let item = tableArray[indexPath.row]
cell.name_label.text = ("\(item.user.firstname) " + "\(item.user.lastname)")
cell.date_label.text = item.createDate
}
return cell
}
推荐阅读
- excel - 将字典存储在数组中
- wso2 - WSO2 Microgateway 对 Soap API 的支持
- php - 如果库可以做同样的事情,CodeIgniter 中帮助程序的实际用途是什么?
- blazor-webassembly - 使用 Blazor 作为组件
- macos - 通过互联网在 OSX 平台上进行远程管理(动态 ip)
- python - 如何在txt中写入参数名称和值列表?
- azure - 获取 azure 存储表字段类型
- reactjs - react.js 中出现错误,TypeError: Cannot read property 'map' of undefined
- python - 内部函数内部的 UnboundLocalError
- jenkins - 如果詹金斯构建失败,我如何阻止用户在 Bitbucket 上合并拉取请求