ios - UITableView 搜索后复选标记位于错误的位置

标签 ios swift uitableview uisearchbar nsindexpath

我想在我的 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
        }
    }
}

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

现在正在运行。

最佳答案

在您的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 在内部重用单元格。因此,当您搜索时,您会说第一个单元格有一个复选标记,然后当您取消时,它会返回到表格并查看单元格,而您的cellForRow代码永远不会告诉它单元格 1 不再被检查,因此它在那里保留复选标记。该单元格不会被重新创建,它已经存在,因此您无法假设它处于什么状态(未检查或已检查)。

关于ios - UITableView 搜索后复选标记位于错误的位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42056123/

相关文章:

swift - CoreML:为什么预测是一个数组?

objective-c - UITableViewCell id 中的 UISwitch 未在视觉上禁用

ios - 如何删除一个单元格并将其放入另一个索引中?

ios - Swift 5,先将VIDEO锁定为Portrait模式,其他VC支持所有方向

ios - Phonegap 应用程序中不同 iOS 设备的不同标记(html 文件)?

iphone - 为特定设备更新 Xcode 8 中的 UI 约束

ios - 如何使用 Swift 保存 TableView 中行的重新排序

ios - 从不正确的线程访问的 Realm

objective-c - iOS 6 之前的 NSAttributedString 是否可用?

ios - 如何根据两个数组中的数据更改 tableview 单元格的样式详细信息如下