我一直在尝试使用复选标记在UITableView上执行SearchBar。用户可以一次只勾选一个。我设法做了勾选和搜索。但是当我搜索并勾选搜索结果时,就是它开始失败的地方
import UIKit
class CandyTableViewController : UITableViewController, UISearchBarDelegate, UISearchDisplayDelegate {
var lastSelectedIndexPath = NSIndexPath(forRow: 0, inSection: 0)
var candies = [Candy]()
var mySelected=String()
var filteredCandies = [Candy]()
override func viewDidLoad() {
self.candies = [Candy(category:"Chocolate", name:"chocolate Bar"),
Candy(category:"Chocolate", name:"chocolate Chip"),
Candy(category:"Chocolate", name:"dark chocolate"),
Candy(category:"Hard", name:"lollipop"),
Candy(category:"Hard", name:"candy cane"),
Candy(category:"Hard", name:"jaw breaker"),
Candy(category:"Other", name:"caramel"),
Candy(category:"Other", name:"sour chew"),
Candy(category:"Other", name:"gummi bear")]
mySelected=candies[lastSelectedIndexPath.row].name
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == self.searchDisplayController!.searchResultsTableView {
return self.filteredCandies.count
} else {
return self.candies.count
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell") as UITableViewCell
cell.accessoryType = .Checkmark
var candy : Candy
if tableView == self.searchDisplayController!.searchResultsTableView {
candy = filteredCandies[indexPath.row]
} else {
candy = candies[indexPath.row]
}
if mySelected==candy.name {
cell.accessoryType = .Checkmark
lastSelectedIndexPath=indexPath
} else {
cell.accessoryType = .None
}
cell.textLabel.text = candy.name
return cell
}
func filterContentForSearchText(searchText: String, scope: String = "All") {
self.filteredCandies = self.candies.filter({( candy : Candy) -> Bool in
var categoryMatch = (scope == "All") || (candy.category == scope)
var stringMatch = candy.name.rangeOfString(searchText)
return categoryMatch && (stringMatch != nil)
})
}
func searchDisplayController(controller: UISearchDisplayController!, shouldReloadTableForSearchString searchString: String!) -> Bool {
let scopes = self.searchDisplayController!.searchBar.scopeButtonTitles as [String]
let selectedScope = scopes[self.searchDisplayController!.searchBar.selectedScopeButtonIndex] as String
self.filterContentForSearchText(searchString, scope: selectedScope)
return true
}
func searchDisplayController(controller: UISearchDisplayController!,
shouldReloadTableForSearchScope searchOption: Int) -> Bool {
let scope = self.searchDisplayController!.searchBar.scopeButtonTitles as [String]
self.filterContentForSearchText(self.searchDisplayController!.searchBar.text, scope: scope[searchOption])
return true
}
func searchDisplayController(controller: UISearchDisplayController, willHideSearchResultsTableView tableView: UITableView) {
self.tableView.reloadData()
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
if indexPath.row != lastSelectedIndexPath?.row {
if let lastSelectedIndexPath = lastSelectedIndexPath {
let oldCell = tableView.cellForRowAtIndexPath(lastSelectedIndexPath)
oldCell?.accessoryType = .None
}
let newCell = tableView.cellForRowAtIndexPath(indexPath)
newCell?.accessoryType = .Checkmark
lastSelectedIndexPath = indexPath
mySelected = newCell?.textLabel.text ?? ""
}
if candies[indexPath.row].name != candies[lastSelectedIndexPath.row].name {
let oldCell = tableView.cellForRowAtIndexPath(lastSelectedIndexPath)
oldCell?.accessoryType = .None
}
let newCell = tableView.cellForRowAtIndexPath(indexPath)
newCell?.accessoryType = .Checkmark
lastSelectedIndexPath = indexPath
mySelected = newCell?.textLabel.text ?? ""
}
}
我希望它能够在搜索后进行复选标记。返回完整列表时,请保持这种状态。请帮助,我已经尝试解决这个问题几天了。
更新:我设法按预期执行。但相信代码可以比这更简单
答案 0 :(得分:2)
您有一个要修复的错误,然后进行一些更改以使搜索结果中的选择显示在常规表视图中。
首先,错误 - 在tableView:didSelectRowAtIndexPath:
中,您正在设置myselected
,如下所示:
myselected=candies[indexPath.row].name
在常规表视图中工作正常,但在搜索结果中,indexPath.row
未指向candies
数组的右侧成员。由于您要跟踪糖果的名称,只需从选定的行中取回名称:
myselected = newCell?.textLabel?.text ?? ""
如果使用此更改运行代码,则不会发现任何差异,因为搜索后您没有重新加载主表视图。为此,请实现委托方法searchDisplayController:willHideSearchResultsTableView:
:
func searchDisplayController(controller: UISearchDisplayController, willHideSearchResultsTableView tableView: UITableView) {
self.tableView.reloadData()
}
几乎就在那里!为表格视图配置单元格时,您将向当前单元格添加复选标记,但不会将其从其他单元格中清除。稍微更改您的代码:
if myselected==candy.name {
cell.accessoryType = .Checkmark
lastSelectedIndexPath=indexPath
} else {
cell.accessoryType = .None
}
答案 1 :(得分:0)
解决方案有点棘手。其中一个问题由@Nate Cook解决:
mySelected = newCell?.textLabel.text ?? ""
第二个问题是在搜索模式和正常模式下正确取消选择。您需要了解NSIndexPath是您的情况的动态值。 E.g:
正常模式下的表(index = indexPath.row)
+-------+------+
| Index | Name |
+-------+------+
| 0 | A |
| 1 | B |
| 2 | C |
| 3 | BB |
+-------+------+
例如,我们选择了第4行,现在我们已经lastSelectedIndexPath = 3
了。如果选择新行,则代码将使用lastSelectedIndexPath正确取消选择行。
但是......让我们看看当您使用关键字 B 激活搜索时会发生什么。
+-------+------+
| Index | Name |
+-------+------+
| 0 | B |
| 1 | BB |
+-------+------+
查看索引,他们改变了!现在,当您尝试选择名称为 B 的行时,您的脚本会尝试取消选择lastIndexPath = 3
行。但是没有这种索引的行,因为你有完全新的索引。
那么我们能做什么?每当UITableView使用Checkmark制作单元格时,我们都可以重新生成lastIndexPath。你已经做到了,这是正确的解决方案,我只是描述了更详细的内容(你在没有描述的情况下改变了你的代码)。
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// cutted some code
cell.accessoryType = .Checkmark
lastSelectedIndexPath=indexPath
}
如果您只有一个复选标记,则代码是最简单的解决方案。如果您需要存储多个复选标记,则需要编写更复杂的代码。这个问题只是关于使用searchController存储1个复选标记。