[英]How to create search function for JSON codable structure data in TableView using Swift 4.2?
[英]How to create UISearchBar to search option for my Tableview data using Swift?
就我而言,我正在尝试为我的tableview
数据实现search
功能。 在这里,我将JSON
数据加载到Tableview section
和rows
。 在自定义cell
我正在显示名称,我想按名称创建搜索。 我尝试了下面的代码,但结果没有任何显示。 如何以适当的方式进行搜索功能。
var sections = [Section]()
var filteredNames = [Section]()
var searchController : UISearchController!
Tableview代表
// MARK: UITableview Delegates
func numberOfSections(in tableView: UITableView) -> Int {
return sections.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if isFiltering {
return filteredNames[section].result.count
} else {
return sections[section].result.count
}
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return sections[section].title
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:MyCustomCell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! MyCustomCell
let item = sections[indexPath.section].result[indexPath.row]
let filteritem = filteredNames[indexPath.section].result[indexPath.row]
if isFiltering {
cell.nameLabel.text = filteritem.name
} else {
cell.nameLabel.text = item.name
}
return cell
}
SearchBarAction和代理
// MARK: UISearchBar Delegates
@IBAction func searchAction(_ sender: Any) {
searchController = UISearchController(searchResultsController: nil)
searchController.hidesNavigationBarDuringPresentation = false
searchController.searchBar.keyboardType = UIKeyboardType.asciiCapable
searchController.searchBar.barTintColor = #colorLiteral(red: 0.317096545, green: 0.5791940689, blue: 0.3803742655, alpha: 1)
searchController.searchBar.backgroundColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
searchController.dimsBackgroundDuringPresentation = false
// Make this class the delegate and present the search
self.searchController.searchBar.delegate = self
searchController.searchResultsUpdater = self
present(searchController, animated: true, completion: nil)
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
guard let searchText = searchBar.text else {
isFiltering = false
return
}
filteredNames = sections[indexPath.section].result[indexPath.row].filter({
return $0.lowercased().contains(searchText.lowercased())
})
isFiltering = filteredNames.count > 0
self.tableView.reloadData()
}
错误:出现错误-使用未解析的标识符'indexPath'; 您是说'IndexPath'吗?
我在这里进行一些计算上的猜测,您可能需要自己进行一些修改。
在我的示例中(上面评论中提供的链接),我只是过滤名称数组。 如果您要过滤各节中的项目,然后删除所有空节,则如果您有多个节则更加困难。
因此,您的filter方法应该看起来像这样:
guard let searchText = searchBar.text else {
isFiltering = false
return
}
self.filteredNames = sections.map({
let filteredResult = $0.result.filter { $0.name.contains(searchText) }
$0.result = filteredResult
return $0
)).filter { !$0.result.isEmpty }
因此,这里您遍历每个部分,然后过滤结果数组以查找搜索字符串中的匹配项,然后删除结果为0的所有部分。
请注意,您可能可以缩短
self.filteredNames = sections.map({
$0.result = $0.result.filter { $0.name.contains(searchText) }
)).filter { !$0.result.isEmpty }
编辑:
import UIKit
import PlaygroundSupport
import UIKit
import PlaygroundSupport
struct Section {
let title: String
var result: [String]
}
class ViewController: UITableViewController {
let searchController = UISearchController(searchResultsController: nil)
let names = [
Section(title: "J", result: [
"John",
"Jason"
]),
Section(title: "M", result: [
"Martin",
"Michael",
"Mattew"
]),
Section(title: "T", result: [
"Terry",
"Thomas"
]),
Section(title: "S", result: ["Steven"])
]
var filteredNames = [Section]()
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Search Example"
searchController.searchResultsUpdater = self
searchController.obscuresBackgroundDuringPresentation = false
searchController.searchBar.placeholder = "Search"
navigationItem.searchController = searchController
definesPresentationContext = true
}
override func numberOfSections(in tableView: UITableView) -> Int {
if isFiltering() {
return filteredNames.count
} else {
return names.count
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if isFiltering() {
return filteredNames[section].result.count
} else {
return names[section].result.count
}
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if isFiltering() {
return filteredNames[section].title
} else {
return names[section].title
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell() // don't do this, i am for example.
var name: String
if isFiltering() {
name = filteredNames[indexPath.section].result[indexPath.row]
} else {
name = names[indexPath.section].result[indexPath.row]
}
cell.textLabel?.text = name
return cell
}
func searchBarIsEmpty() -> Bool {
// Returns true if the text is empty or nil
return searchController.searchBar.text?.isEmpty ?? true
}
func isFiltering() -> Bool {
return searchController.isActive && !searchBarIsEmpty()
}
func filterContentForSearchText(_ searchText: String, scope: String = "All") {
filteredNames = names.map({
let result = $0.result.filter {
$0.localizedLowercase.contains(searchText.lowercased())
}
return Section(title: $0.title, result: result)
}).filter { !$0.result.isEmpty }
tableView.reloadData()
}
}
extension ViewController: UISearchResultsUpdating {
func updateSearchResults(for searchController: UISearchController) {
filterContentForSearchText(searchController.searchBar.text!)
}
}
let vc = ViewController()
let nav = UINavigationController()
nav.viewControllers = [vc]
PlaygroundPage.current.liveView = nav
首先,您正在过滤部分,因此将数组命名为
var filteredSections = [Section]()
filteredNames具有误导性,并暗示该数组为[String]
一种可能的解决方案是使用过滤后的内容创建新部分
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if !searchText.isEmpty {
filteredSections = sections.compactMap { section -> Section? in
let filteredContent = section.result.filter {$0.name.range(of: searchText, options: .caseInsensitive) != nil }
return filteredContent.isEmpty ? nil : Section(title: section.title, result: filteredContent)
}
isFiltering = true
} else {
filteredSections.removeAll()
isFiltering = false
}
self.tableView.reloadData()
}
并且表视图数据源的方法必须更改为
func numberOfSections(in tableView: UITableView) -> Int {
return isFiltering ? filteredSections.count : sections.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let currentSection = isFiltering ? filteredSections[section] : sections[section]
return currentSection.result.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return isFiltering ? filteredSections[section].title : sections[section].title
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath) as! MyCustomCell
let section = isFiltering ? filteredSections[indexPath.section] : sections[indexPath.section]
let item = section.result[indexPath.row]
cell.nameLabel.text = item.name
return cell
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.