搜索后,UITableView 在错误的地方打勾 [英] UITableView Checkmarks at the wrong place after search

查看:36
本文介绍了搜索后,UITableView 在错误的地方打勾的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在我的 tableView 中搜索,设置复选标记并将带有复选标记的对象保存在 Realm 中.但是,如果我在搜索后设置复选标记并取消搜索,则复选标记位于我单击的 indexPath 上,而不是在对象上.我无法更好地解释它,所以这里有一个例子:搜索练习后.

我点击取消按钮后

这是我的代码:

class ShowExcercisesTableViewController: UITableViewController, UISearchResultsUpdating, UISearchBarDelegate {//特性让领域=尝试!领域()var request2:结果<练习>?{已设置{tableView.reloadData()}}var searchOrNot:锻炼?var searchResults = 试试!Realm().objects(Excercise.self)var resultSearchController: UISearchController!var shouldShowSearchResults = falsevar 肌肉组搜索:字符串?//搜索栏功能func filterResultsWithSearchString(searchString: String){让谓词 = NSPredicate(格式:名称包含 [c]%@ AND 肌肉组 =%@ AND 复制 = 假",searchString,muscleGroupForSearch!)searchResults = realm.objects(Excercise.self).filter(predicate).sorted(byProperty: "name", 升序: true)}func updateSearchResults(for searchController: UISearchController) {让 searchString = searchController.searchBar.textfilterResultsWithSearchString(searchString: searchString!)tableView.reloadData()}func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {shouldShowSearchResults = truetableView.reloadData()}func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {shouldShowSearchResults = falsetableView.reloadData()}func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {如果 !shouldShowSearchResults {shouldShowSearchResults = truetableView.reloadData()}resultSearchController.searchBar.resignFirstResponder()}//生命周期覆盖 func viewDidLoad() {super.viewDidLoad()self.resultSearchController = ({让控制器 = UISearchController(searchResultsController: nil)controller.searchResultsUpdater = selfcontroller.searchBar.delegate = selfcontroller.dimsBackgroundDuringPresentation = false控制器.searchBar.sizeToFit()controller.searchBar.placeholder = "这样的 Übungen..."self.tableView.tableHeaderView = controller.searchBar返回控制器})()self.tableView.reloadData()}//TableView功能覆盖 func tableView(_ tableView: UITableView, numberOfRowsInSection 部分: Int) ->整数{如果 shouldShowSearchResults {返回 searchResults.count}别的{返回 request2!.count}}覆盖 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) ->UITableViewCell {让单元格:ShowExcercisesTableViewCell = tableView.dequeueReusableCell(withIdentifier: CellIdentifier.showExcercises, for: indexPath) as!ShowExcercisesTableViewCellif shouldShowSearchResults{让练习 = searchResults[indexPath.row]cell.nameLabel.text = 练习.name如果来自培训计划{如果 excercise.selected == true{cell.accessoryType = .checkmark}别的{cell.accessoryType = .none}}返回单元格}别的{let excercise = request2![indexPath.row]cell.nameLabel.text = 练习.name如果来自培训计划{如果 excercise.selected == true{cell.accessoryType = .checkmark}别的{cell.accessoryType = .none}}返回单元格}}//对勾覆盖 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {如果 fromTrainingPlan == true &&request2 != nil{if shouldShowSearchResults{searchOrNot = searchResults[indexPath.row]}别的{searchOrNot = request2![indexPath.row]}tableView.deselectRow(at: indexPath, 动画: true)让单元格:ShowExcercisesTableViewCell = tableView.cellForRow(at: indexPath) as!ShowExcercisesTableViewCell做 {尝试realm.write {searchOrNot!.selected = !searchOrNot!.selected}}抓住{打印(错误)}如果 searchOrNot!.selected {cell.accessoryType = .checkmark}别的 {cell.accessoryType = .none}}}

抱歉有这么多代码,我不确定什么是相关的,什么不是.有没有办法在搜索后在正确的位置设置复选标记?提前致谢!

现在可以使用了.

解决方案

复选标记位于我单击的 indexPath 处

你没有告诉代码你想要复选标记的indexPath.当您的单元格被重用时:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) ->UITableViewCell {

您需要保留对应该选择的 indexPath 的引用并显示复选标记,以便单元格在内部重用时在正确的 indexPath 上显示复选标记.

似乎有些人在没有阅读框架的工作原理和阅读 苹果文档.

可重复使用的单元格

prepareForReuse

<块引用>

如果一个 UITableViewCell 对象是可重用的——也就是说,它有一个重用identifier——这个方法在返回对象之前调用来自 UITableView 方法 dequeueReusableCellWithIdentifier:.为了性能原因,您应该只重置单元格的属性与内容无关,例如 alpha、编辑和 选择状态.tableView:cellForRowAtIndexPath 中表格视图的委托:重用单元格时应始终重置所有内容.如果细胞对象没有关联的重用标识符,此方法是不叫.如果覆盖此方法,则必须确保调用超类实现.

I want to search in my tableView, set checkmarks and save the objects with the checkmarks in Realm. But if I set a checkmark after a search and cancel the search, the checkmark is at the indexPath that I clicked on, and not at the object. I can't explain it better, so here's an example: After I search an exercise.

After I clicked the cancel button

Here's my code:

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
        }
    }
}

Sorry for so much code, I'm not sure what is relevant and what not. Is there any way to set the checkmarks at the right places after the search? Thanks in advance!

It's working now.

解决方案

the checkmark is at the indexPath that I clicked on

You are not telling the code on what indexPath you want the checkmark. When your cell gets reused :

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

You need to keep a reference to what indexPath is supposed to be selected and show the checkMark so the cells shows the checkMark on the correct indexPath when the cells are reused internally.

EDIT:

Seems some people downvote and modify my answers as their own without reading how the framework works and reading Apples Documentation.

Reusable Cells

prepareForReuse

If a UITableViewCell object is reusable—that is, it has a reuse identifier—this method is invoked just before the object is returned from the UITableView method dequeueReusableCellWithIdentifier:. For performance reasons, you should only reset attributes of the cell that are not related to content, for example, alpha, editing, and selection state. The table view's delegate in tableView:cellForRowAtIndexPath: should always reset all content when reusing a cell. If the cell object does not have an associated reuse identifier, this method is not called. If you override this method, you must be sure to invoke the superclass implementation.

这篇关于搜索后,UITableView 在错误的地方打勾的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆