UITableView Checkmarks 在错误的地方搜索后
Posted
技术标签:
【中文标题】UITableView Checkmarks 在错误的地方搜索后【英文标题】:UITableView Checkmarks at the wrong place after search 【发布时间】:2017-02-05 19:14:19 【问题描述】:我想在我的 tableView 中搜索,设置复选标记并将带有复选标记的对象保存在 Realm 中。但是,如果我在搜索后设置复选标记并取消搜索,则复选标记位于我单击的 indexPath 处,而不是对象处。我无法更好地解释它,所以这里有一个例子: After I search an exercise.
After I clicked the cancel button
这是我的代码:
class ShowExcercisesTableViewController: UITableViewController, UISearchResultsUpdating, UISearchBarDelegate
//Properties
let realm = try! Realm()
var request2: Results<Excercise>?
didSet
tableView.reloadData()
var searchOrNot: Excercise?
var searchResults = try! Realm().objects(Excercise.self)
var resultSearchController: UISearchController!
var shouldShowSearchResults = false
var muscleGroupForSearch: String?
//Searchbar Funktionen
func filterResultsWithSearchString(searchString: String)
let predicate = NSPredicate(format: "name CONTAINS [c]%@ AND muscleGroup =%@ AND copied = false", searchString, muscleGroupForSearch!)
searchResults = realm.objects(Excercise.self).filter(predicate).sorted(byProperty: "name", ascending: true)
func updateSearchResults(for searchController: UISearchController)
let searchString = searchController.searchBar.text
filterResultsWithSearchString(searchString: searchString!)
tableView.reloadData()
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar)
shouldShowSearchResults = true
tableView.reloadData()
func searchBarCancelButtonClicked(_ searchBar: UISearchBar)
shouldShowSearchResults = false
tableView.reloadData()
func searchBarSearchButtonClicked(_ searchBar: UISearchBar)
if !shouldShowSearchResults
shouldShowSearchResults = true
tableView.reloadData()
resultSearchController.searchBar.resignFirstResponder()
//Lifecycle
override func viewDidLoad()
super.viewDidLoad()
self.resultSearchController = (
let controller = UISearchController(searchResultsController: nil)
controller.searchResultsUpdater = self
controller.searchBar.delegate = self
controller.dimsBackgroundDuringPresentation = false
controller.searchBar.sizeToFit()
controller.searchBar.placeholder = "Suche Übungen..."
self.tableView.tableHeaderView = controller.searchBar
return controller
)()
self.tableView.reloadData()
//TableView Funktionen
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
if shouldShowSearchResults
return searchResults.count
else
return request2!.count
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell: ShowExcercisesTableViewCell = tableView.dequeueReusableCell(withIdentifier: CellIdentifier.showExcercises, for: indexPath) as! ShowExcercisesTableViewCell
if shouldShowSearchResults
let excercise = searchResults[indexPath.row]
cell.nameLabel.text = excercise.name
if fromTrainingPlan
if excercise.selected == true
cell.accessoryType = .checkmark
else
cell.accessoryType = .none
return cell
else
let excercise = request2![indexPath.row]
cell.nameLabel.text = excercise.name
if fromTrainingPlan
if excercise.selected == true
cell.accessoryType = .checkmark
else
cell.accessoryType = .none
return cell
//Checkmarks
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
if fromTrainingPlan == true && request2 != nil
if shouldShowSearchResults
searchOrNot = searchResults[indexPath.row]
else
searchOrNot = request2![indexPath.row]
tableView.deselectRow(at: indexPath, animated: true)
let cell: ShowExcercisesTableViewCell = tableView.cellForRow(at: indexPath) as! ShowExcercisesTableViewCell
do
try realm.write
searchOrNot!.selected = !searchOrNot!.selected
catch
print(error)
if searchOrNot!.selected
cell.accessoryType = .checkmark
else
cell.accessoryType = .none
抱歉,代码太多了,我不确定什么是相关的,什么不是。有没有办法在搜索后在正确的位置设置复选标记?提前致谢!
现在可以了。
【问题讨论】:
cell.accessoryType = selectedCells.contains(indexPath) ? .Checkmark : .None 和 cellForRowAt 尝试将代码放在您在willDisplayCell
中设置复选标记的位置
我也用willDisplayCell试过了,结果一样
@NazmulHasan,我不明白你的意思,对不起,我是 Swift 的新手
.selected
和 fromTrainingPlan
是什么?
【参考方案1】:
在您的cellForRowAtIndexPath
中,您需要禁用不需要它的单元格的复选标记。您只启用了这样做的单元格。
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell: ShowExcercisesTableViewCell = tableView.dequeueReusableCell(withIdentifier: CellIdentifier.showExcercises, for: indexPath) as! ShowExcercisesTableViewCell
if shouldShowSearchResults
let excercise = searchResults[indexPath.row]
cell.nameLabel.text = excercise.name
if excercise.selected == true
cell.accessoryType = .checkmark
else
cell.accessoryType = .none // Add this code here
return cell
else
let excercise = request2![indexPath.row]
cell.nameLabel.text = excercise.name
if excercise.selected == true
cell.accessoryType = .checkmark
else
cell.accessoryType = .none // Add this code here
return cell
UITableViews
在内部重用单元格。因此,当您搜索时,您说的是cell one has a checkmark
,然后当您取消时,它会返回表格并查看单元格,而您的cellForRow
代码永远不会告诉它不再检查单元格一,因此它保持复选标记那里。单元格没有被重新创建,它已经存在,所以你不能假设它处于什么状态(未检查或检查)。
【讨论】:
你对我的回答投了反对票,并告诉我我错了,代码 cellForRowAtIndexPath 不知道应该标记哪个单元格,你基本上重复了完全相同的事情。我明确地说 cellForRowAtIndexPath 不知道应该标记哪个单元格,您重复了我的回答。恭喜你复制了我的答案。如果他想在 cellForRowAtIndexPath 中放置多个选项,或者更确切地说是多个单元格,会发生什么情况?那么您复制的“答案”中的“If / Else”语句将完全失败并选中/取消选中所有单元格。 @Sneak Ummmm,我的答案绝不是你的副本。你在我的发布后编辑了你的。您发布的是“您需要保存对索引路径的引用”的 3 行文本。如果您认为我在攻击您或其他什么,我深表歉意,但您的回答是错误的。如果您更正它,我将删除我的反对票。 "你在我的发布后编辑了你的。" , uummmmmmm 是的,我编辑了它并添加了 Apple 文档供您阅读,也许您看不到 EDIT 标记? 我尝试了您的解决方案,但不幸的是它不起作用。行为发生了一些变化。现在,如果我在开始搜索之前选择 tableView 中的对象,然后使用搜索,则正确的对象将保持选中状态。但是,如果我在使用搜索栏后从 searchResults 数组中选择对象,然后使用搜索栏的取消按钮,以便再次显示 request2 数组,则选择了错误的对象。也许还有其他想法?顺便说一句:对不起我的英语不好 现在可以使用了!我只在 didSelectRow 函数中做了一点改动。我编辑了我的问题。【参考方案2】:复选标记位于我单击的 indexPath 处
你没有告诉代码你想要复选标记的indexPath
。当您的单元格被重复使用时:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
您需要保留对应该选择的 indexPath 的引用并显示复选标记,以便在内部重用单元格时,单元格会在正确的 indexPath 上显示复选标记。
编辑:
似乎有些人没有阅读框架的工作原理和阅读Apples Documentation.
可重复使用的细胞
prepareForReuse
如果 UITableViewCell 对象是可重用的——也就是说,它具有重用性 标识符——这个方法在对象返回之前被调用 从 UITableView 方法 dequeueReusableCellWithIdentifier:.为了 性能原因,您应该只重置单元格的属性 与内容无关,例如 alpha、编辑和选择 状态。 tableView:cellForRowAtIndexPath 中的 table view 的委托: 重用单元格时应始终重置所有内容。如果细胞 对象没有关联的重用标识符,此方法是 不叫。如果你重写这个方法,你必须确保调用 超类实现。
【讨论】:
投反对票,因为这是不正确的。他正在检查是否选择了某些东西并根据它确定复选标记。他不需要以任何方式保存索引路径。 当然,你的答案是我的完美副本。如果他想在 cellForRowAtIndexPath 中放置多个选项,或者更确切地说是多个单元格,会发生什么?那么您复制的“答案”中的“If / Else”语句将完全失败并选中/取消选中所有单元格。 您对you need to keep a reference to what indexPath is supposed to be selected
的回答是错误的。对不起。
@ColdLogic 也许我的英语不太好,但让我们再试一次:“如果他想在 cellForRowAtIndexPath 中放置多个选项,或者更确切地说是多个单元格,会发生什么?” 或者 Apple 文档是错误的,但你是对的。
如果他要使用多个单元格,那么他将使用他的解决方案来检查数据并据此确定复选标记。如果他要保存对 indexPath 的引用,他将没有数据和 indexPath 之间的链接,因此会遇到同样的问题。没有我在哪里说“苹果文档是错误的”。我说你解决问题的方法是错误的。如果您想加入聊天,我将非常乐意帮助您解决问题。以上是关于UITableView Checkmarks 在错误的地方搜索后的主要内容,如果未能解决你的问题,请参考以下文章