Ios 具有多节数组和行数据数组搜索实现的Swift UITableview自定义单元格
在我的场景中,我尝试创建带有多个节和单元格的Ios 具有多节数组和行数据数组搜索实现的Swift UITableview自定义单元格,ios,swift,Ios,Swift,在我的场景中,我尝试创建带有多个节和单元格的UITableview自定义单元格。在这里,我想添加两件事复选标记和search选项,这两件事我都尝试过使用下面的代码,但都不起作用 下面是我的代码。如何解决这个问题 class CustomCell: UITableViewCell { @IBOutlet weak var NameLabel: UILabel! @IBOutlet weak var CountLabel: UILabel! override func
UITableview
自定义单元格。在这里,我想添加两件事复选标记和search
选项,这两件事我都尝试过使用下面的代码,但都不起作用
下面是我的代码。如何解决这个问题
class CustomCell: UITableViewCell {
@IBOutlet weak var NameLabel: UILabel!
@IBOutlet weak var CountLabel: UILabel!
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
self.accessoryType = selected ? .checkmark : .none
}
}
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchControllerDelegate, UISearchResultsUpdating, UISearchBarDelegate {
var searchController : UISearchController!
let sectionData = ["1", "2"]
let rowNames = [["A", "B", "C"], ["D", "E", "F"]]
var filteredData: [[String]]!
let cellReuseIdentifier = "cell"
@IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
filteredData = rowNames
}
//MARK: List Tableview
func numberOfSections(in tableView: UITableView) -> Int {
return sectionData.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return sectionData[section]
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return filteredData[section].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:CustomCell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! CustomCell
cell.NameLabel.text = filteredData[indexPath.section][indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.tableView.deselectRow(at: indexPath, animated: true)
}
//MARK: Search Delegate
func updateSearchResults(for searchController: UISearchController) {
if let searchText = searchController.searchBar.text {
filteredData = searchText.isEmpty ? rowNames : rowNames.filter({(dataString: String) -> Bool in
return dataString.range(of: searchText, options: .caseInsensitive) != nil
})
Self.tableView.reloadData()
}
}
}
我强烈建议你更换
let sectionData = ["1", "2"]
let rowNames = [["A", "B", "C"], ["D", "E", "F"]]
与
将filteredData
声明为[String:[String]]?
,而不是[[String]]代码>
然后,您可以使用以下代码过滤tableViewData
:
filteredData = tableViewData.compactMapValues { currentSection -> [String]? in
let filteredRow = currentSection.filter {
$0.range(of: searchText, options: .caseInsensitive) != nil
}
return filteredRow.isEmpty ? nil : filteredRow
}
添加新属性var Filteredatakeys:[字符串]?
并在每次更新Filteredata
后更新它:Filteredatakeys=Filteredata?.keys.sorted()
并使用以下UITableViewDataSource
方法:
func numberOfSections(in tableView: UITableView) -> Int {
return filteredDataKeys?.count ?? 0
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return filteredDataKeys?[section]
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
guard let keyForSection = filteredDataKeys?[section] else {
return 0
}
return filteredData?[keyForSection]?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! CustomCell
guard let keyForSection = filteredDataKeys?[indexPath.section] else {
return cell
}
let textForRow = filteredData?[keyForSection]?[indexPath.row]
cell.NameLabel.text = textForRow
return cell
}
我强烈建议你更换
let sectionData = ["1", "2"]
let rowNames = [["A", "B", "C"], ["D", "E", "F"]]
与
将filteredData
声明为[String:[String]]?
,而不是[[String]]代码>
然后,您可以使用以下代码过滤tableViewData
:
filteredData = tableViewData.compactMapValues { currentSection -> [String]? in
let filteredRow = currentSection.filter {
$0.range(of: searchText, options: .caseInsensitive) != nil
}
return filteredRow.isEmpty ? nil : filteredRow
}
添加新属性var Filteredatakeys:[字符串]?
并在每次更新Filteredata
后更新它:Filteredatakeys=Filteredata?.keys.sorted()
并使用以下UITableViewDataSource
方法:
func numberOfSections(in tableView: UITableView) -> Int {
return filteredDataKeys?.count ?? 0
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return filteredDataKeys?[section]
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
guard let keyForSection = filteredDataKeys?[section] else {
return 0
}
return filteredData?[keyForSection]?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! CustomCell
guard let keyForSection = filteredDataKeys?[indexPath.section] else {
return cell
}
let textForRow = filteredData?[keyForSection]?[indexPath.row]
cell.NameLabel.text = textForRow
return cell
}
我建议做一些这样的修改
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchControllerDelegate, UISearchResultsUpdating, UISearchBarDelegate {
var searchController : UISearchController!
var rowNames = [[(value: "A",selected: false),(value: "B",selected: false),(value:"C",selected:false)],[(value: "D",selected: false),(value: "E",selected:false),(value:"F",selected:false)]]
var filteredData: [[(value:String,selected:Bool)]]!
let cellReuseIdentifier = "cell"
@IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
//filteredData = rowNames
}
//MARK: List Tableview
func numberOfSections(in tableView: UITableView) -> Int {
return rowNames.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return (section + 1).description
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searchController.searchBar.text != nil && searchController.searchBar.text != ""{
return filteredData.count
}else{
return rowNames[section].count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:CustomCell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! CustomCell
if searchController.searchBar.text != nil && searchController.searchBar.text != ""{
cell.NameLabel.text = filteredData[indexPath.section][indexPath.row].value
}else{
cell.NameLabel.text = rowNames[indexPath.section][indexPath.row].value
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)
if searchController.searchBar.text == nil || searchController.searchBar.text == ""{
if rowNames[indexPath.section][indexPath.row].selected == true{
cell?.accessoryType = .none
rowNames[indexPath.section][indexPath.row].selected = false
}else{
cell?.accessoryType = .checkmark
rowNames[indexPath.section][indexPath.row].selected = true
}
}
//self.tableView.deselectRow(at: indexPath, animated: true)
}
//MARK: Search Delegate
func updateSearchResults(for searchController: UISearchController) {
if let searchText = searchController.searchBar.text, searchController.searchBar.text != "" {
})
filteredData = rowNames.map({row in
row.filter({
$0.value.contains(searchText)
}).map({$0})
})
self.tableView.reloadData()
}
}
}
由于要在选定的单元格上设置复选标记,因此必须在数据源中跟踪该单元格的状态。这就是为什么如果你使用一个结构,模型会变成一个元组,你可以添加一个sleceted字段,并且在你的
didSelectRow功能您必须跟踪模型的状态才能显示或不显示复选标记。搜索不值得搜索,因为没有用于搜索的文本,因此应用程序不应重新加载tableView。我建议进行一些类似的更改
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchControllerDelegate, UISearchResultsUpdating, UISearchBarDelegate {
var searchController : UISearchController!
var rowNames = [[(value: "A",selected: false),(value: "B",selected: false),(value:"C",selected:false)],[(value: "D",selected: false),(value: "E",selected:false),(value:"F",selected:false)]]
var filteredData: [[(value:String,selected:Bool)]]!
let cellReuseIdentifier = "cell"
@IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
//filteredData = rowNames
}
//MARK: List Tableview
func numberOfSections(in tableView: UITableView) -> Int {
return rowNames.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return (section + 1).description
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searchController.searchBar.text != nil && searchController.searchBar.text != ""{
return filteredData.count
}else{
return rowNames[section].count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:CustomCell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! CustomCell
if searchController.searchBar.text != nil && searchController.searchBar.text != ""{
cell.NameLabel.text = filteredData[indexPath.section][indexPath.row].value
}else{
cell.NameLabel.text = rowNames[indexPath.section][indexPath.row].value
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)
if searchController.searchBar.text == nil || searchController.searchBar.text == ""{
if rowNames[indexPath.section][indexPath.row].selected == true{
cell?.accessoryType = .none
rowNames[indexPath.section][indexPath.row].selected = false
}else{
cell?.accessoryType = .checkmark
rowNames[indexPath.section][indexPath.row].selected = true
}
}
//self.tableView.deselectRow(at: indexPath, animated: true)
}
//MARK: Search Delegate
func updateSearchResults(for searchController: UISearchController) {
if let searchText = searchController.searchBar.text, searchController.searchBar.text != "" {
})
filteredData = rowNames.map({row in
row.filter({
$0.value.contains(searchText)
}).map({$0})
})
self.tableView.reloadData()
}
}
}
由于要在选定的单元格上设置复选标记,因此必须在数据源中跟踪该单元格的状态。这就是为什么如果你使用一个结构,模型会变成一个元组,你可以添加一个sleceted字段,并且在你的
didSelectRow功能您必须跟踪模型的状态才能显示或不显示复选标记。搜索不值得搜索,因为没有搜索文本,因此应用程序不应重新加载tableView。sectionData=Filteredata before tableView.reloadData()@AlexandrKolesnik我遇到错误-类型“[String]”的值在返回数据字符串时没有成员“range”。range(of:searchText,options:.Case不区分大小写)!=零线。另外,我想为这个使用更好的代码。datastring.lowercased().contains(searchText.lowercased())filteredData=searchText.isEmpty?projects:projects.filter({(dataString:[String])->Bool in return dataString.lowercased().contains(searchText.lowercased())})显示类型“[String]”的错误值没有成员“lowercased”@AlexandrKolesnikin问题您的dataString:String在注释dataString:[String]中它对搜索很重要,对于数组,您应该执行类似smth的数据字符串。首先(其中:{$0.lowercased().contains(searchText.lowercased())})sectionData=Filteredata before tableView.reloadData()@AlexandrKolesnik我面临错误-类型“[String]”的值在返回数据字符串时没有成员“range”。range(of:searchText,选项:.CaseSensitive)!=零线。另外,我想为这个使用更好的代码。datastring.lowercased().contains(searchText.lowercased())filteredData=searchText.isEmpty?projects:projects.filter({(dataString:[String])->Bool in return dataString.lowercased().contains(searchText.lowercased())})显示类型“[String]”的错误值没有成员“lowercased”@AlexandrKolesnikin问题您的dataString:String在注释dataString:[String]中它对搜索很重要,对于数组,您应该先执行类似于smth的dataString.first(其中:{$0.lowercased().contains(searchText.lowercased())}),这是一个很好的解决方案。顺便说一句,您可以使用Struct进行更新,因为我将在将来用于此JSON数据加载@Roman PodymovThanks@Roman Podymov顺便说一句,我们不能在numberofrows guard let keyForSection=Filteredata?.keys.sorted()[indexPath.section]中分配return 0,否则{return 0}@BenDev为什么不能?据我所知,如果searchText==“G”
表中将没有行。让我们来看看。感谢老兄,这是一个很好的解决方案。顺便说一句,您可以使用Struct进行更新,因为我将在将来用于此JSON数据加载@Roman PodymovThanks@Roman Podymov顺便说一句,我们不能在numberofrows guard let keyForSection=Filteredata?.keys.sorted()[indexPath.section]中分配return 0,否则{return 0}@BenDev为什么不能?据我所知,如果searchText==“G”
表中将没有行。让我们。我认为section.description缺少@kjoeThanks,我将检查它。但我仍然没有得到完美的答案,因为我要加载JSON数据,所以如果有人使用带解释的struct。@kjoeman会更好,然后你应该发布一个带有struc和json struc而不是相对数据的问题,你想要一个不问问题的答案,尝试在github中发布一个MVP以进行分类,因为这段代码几乎是带有struc和jsonI think section.description的代码的一部分。缺少@kjoeThanks我会检查它。但我仍然没有得到完美的答案,因为我要加载JSON数据,所以如果有人使用带解释的struct。@kjoeman会更好,然后你应该发布一个带有struc和json的问题struc而不是相对数据,你想要一个不问问题的答案,试着在github中发布一个MVP进行分类,因为这段代码几乎是带有struc和json的代码的一部分