如何使用已解析的 JSON 文件在表视图中添加搜索栏
how to add a searchbar in a tableview with a parsed JSON file
我已成功将具有以下数据模型的 JSON 文件解析到我的项目和表格视图中。
import Foundation
struct ActionResult: Codable {
let data: [Datum]
}
struct Datum: Codable {
let goalTitle, goalDescription, goalImage: String
let action: [Action]
}
struct Action: Codable {
let actionID: Int
let actionTit: String
}
现在我正在尝试创建一个搜索栏来搜索“actionTitle”。我的表格视图有部分 headers 和行。
相关代码:
var filteredData: [Action]?
let searchController = UISearchController()
override func viewDidLoad() {
super.viewDidLoad()
title = "Search"
searchController.searchBar.delegate = self
filteredData = ????
navigationItem.searchController = searchController
parseJSON()
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
filteredData = []
if searchText == ""{
filteredData = ????
}
else {
for actions in ???? {
if actions.lowercased().contains(searchText.lowercased()) {
filteredData.append(actions)
}
self.tableView.reloadData()
}
我不知道在我有的地方使用什么代码????。
谢谢。
您想保留所有可用数据的实例 (allActions
),并始终在 tableView 中显示您的筛选数据 (filteredData
)。所以当没有什么可以过滤的时候,filteredData
等于allActions
(除非你打算在搜索为空的时候隐藏所有数据)。
调用searchBar(_:,textDidChange:)
时,可以在过滤器闭包上使用filter(_:) to evaluate if the item should be included. Apple's description:
A closure that takes an element of the sequence as its argument and
returns a Boolean value indicating whether the element should be
included in the returned array.
不知道声明filteredData: [Action]?
有没有什么具体原因,是不是调用了parseJSON()
才填充数据?如果是这样——我建议初始化一个空数组并在数据可用时填充它们。
此外,parseData()
会生成 Datum
的实例吗?我相信你的这段代码不包括在内,所以我添加 datum: Datum?
。
如果我错了,请提供更多信息 parseJSON()
填充的内容,我会更新我的答案。
var result: ActionResult? {
didSet {
guard let result = result else { return }
allSectionDataActionMap = Dictionary(uniqueKeysWithValues: result.data.enumerated().map { ([=10=].0, ([=10=].1, [=10=].1.actions)) })
updateFilteredData()
}
}
var allSectionDataActionMap = [Int: (datum: Datum, actions: [Action])]()
// Maps the section index to the Datum & filtered [Action]
var filteredSectionDataActions = [Int: (datum: Datum, actions: [Action])]()
let searchController = UISearchController()
override func viewDidLoad() {
super.viewDidLoad()
title = "Search"
searchController.searchBar.delegate = self
navigationItem.searchController = searchController
// ...
parseJSON()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return filteredSectionDataActions.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return filteredSectionDataActions[section]?.actions.count ?? 0
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") ?? UITableViewCell(style: .default, reuseIdentifier: "cell")
if let action = filteredSectionDataActions[indexPath.section]?.actions[indexPath.row] {
// setup cell for action
cell.textLabel?.text = action.actionTitle
}
return cell
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
updateFilteredData(for: searchText.lowercased())
tableView.reloadData()
}
func updateFilteredData(for searchText: String = String()) {
if searchText.isEmpty {
filteredSectionDataActions = allSectionDataActionMap
} else {
for (index, (datum, actions)) in allSectionDataActionMap {
let filteredActions = actions.filter { [=10=].actionTitle.lowercased().contains(searchText) }
if filteredActions.isEmpty {
filteredSectionDataActions[index] = (datum, actions)
} else {
filteredSectionDataActions[index] = (datum, filteredActions)
}
}
}
}
我已成功将具有以下数据模型的 JSON 文件解析到我的项目和表格视图中。
import Foundation
struct ActionResult: Codable {
let data: [Datum]
}
struct Datum: Codable {
let goalTitle, goalDescription, goalImage: String
let action: [Action]
}
struct Action: Codable {
let actionID: Int
let actionTit: String
}
现在我正在尝试创建一个搜索栏来搜索“actionTitle”。我的表格视图有部分 headers 和行。
相关代码:
var filteredData: [Action]?
let searchController = UISearchController()
override func viewDidLoad() {
super.viewDidLoad()
title = "Search"
searchController.searchBar.delegate = self
filteredData = ????
navigationItem.searchController = searchController
parseJSON()
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
filteredData = []
if searchText == ""{
filteredData = ????
}
else {
for actions in ???? {
if actions.lowercased().contains(searchText.lowercased()) {
filteredData.append(actions)
}
self.tableView.reloadData()
}
我不知道在我有的地方使用什么代码????。
谢谢。
您想保留所有可用数据的实例 (allActions
),并始终在 tableView 中显示您的筛选数据 (filteredData
)。所以当没有什么可以过滤的时候,filteredData
等于allActions
(除非你打算在搜索为空的时候隐藏所有数据)。
调用searchBar(_:,textDidChange:)
时,可以在过滤器闭包上使用filter(_:) to evaluate if the item should be included. Apple's description:
A closure that takes an element of the sequence as its argument and returns a Boolean value indicating whether the element should be included in the returned array.
不知道声明filteredData: [Action]?
有没有什么具体原因,是不是调用了parseJSON()
才填充数据?如果是这样——我建议初始化一个空数组并在数据可用时填充它们。
此外,parseData()
会生成 Datum
的实例吗?我相信你的这段代码不包括在内,所以我添加 datum: Datum?
。
如果我错了,请提供更多信息 parseJSON()
填充的内容,我会更新我的答案。
var result: ActionResult? {
didSet {
guard let result = result else { return }
allSectionDataActionMap = Dictionary(uniqueKeysWithValues: result.data.enumerated().map { ([=10=].0, ([=10=].1, [=10=].1.actions)) })
updateFilteredData()
}
}
var allSectionDataActionMap = [Int: (datum: Datum, actions: [Action])]()
// Maps the section index to the Datum & filtered [Action]
var filteredSectionDataActions = [Int: (datum: Datum, actions: [Action])]()
let searchController = UISearchController()
override func viewDidLoad() {
super.viewDidLoad()
title = "Search"
searchController.searchBar.delegate = self
navigationItem.searchController = searchController
// ...
parseJSON()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return filteredSectionDataActions.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return filteredSectionDataActions[section]?.actions.count ?? 0
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") ?? UITableViewCell(style: .default, reuseIdentifier: "cell")
if let action = filteredSectionDataActions[indexPath.section]?.actions[indexPath.row] {
// setup cell for action
cell.textLabel?.text = action.actionTitle
}
return cell
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
updateFilteredData(for: searchText.lowercased())
tableView.reloadData()
}
func updateFilteredData(for searchText: String = String()) {
if searchText.isEmpty {
filteredSectionDataActions = allSectionDataActionMap
} else {
for (index, (datum, actions)) in allSectionDataActionMap {
let filteredActions = actions.filter { [=10=].actionTitle.lowercased().contains(searchText) }
if filteredActions.isEmpty {
filteredSectionDataActions[index] = (datum, actions)
} else {
filteredSectionDataActions[index] = (datum, filteredActions)
}
}
}
}