首页 > 解决方案 > UISearchController:indexPath 不随原始数组改变

问题描述

通过示例更容易解释。我有原始数组,它是搜索和过滤数组与搜索项。如果我在搜索后找到一个项目并点击它,我将其标记为完成(我有待办事项列表),但是当我取消搜索时,我发现原始数组中的第一个元素被标记,而不是第三个项目。我搜索了一些线程并发现几乎类似的问题,但解决方案不适合我的问题。例如: 过滤后的 didSelectRowAtIndexPath indexpath UISearchController - Swift

这里有一些代码。特别是在didSelectRowAt我标记要完成的项目时。有没有人有任何想法?

private var searchBarIsEmpty: Bool {
    guard let text = searchController.searchBar.text else { return false }
    return text.isEmpty
}
private var isFiltering: Bool {
    return searchController.isActive && !searchBarIsEmpty
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if isFiltering {
        return filteredTasks?.count ?? 0
    }
    return manager.tasks.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: Keys.cell.rawValue, for: indexPath) as! ToDoCell
    var currentItem: Task
    if isFiltering {
        currentItem = filteredTasks?[indexPath.row] ?? manager.tasks[indexPath.row]
    } else {
        currentItem = manager.tasks[indexPath.row]
    }

    cell.titleLabel.text = currentItem.taskName
    cell.descriptionLabel.text = currentItem.description

    return cell
}

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: true)
    let accessoryType: UITableViewCell.AccessoryType = manager.changeState(at: indexPath.row) ? .checkmark : .none
    tableView.cellForRow(at: indexPath)?.accessoryType = accessoryType
}

标签: swift

解决方案


当你使用 tableView.dequeueReusableCell 时,你可能会得到旧的单元格,所以你应该更新它。你应该阅读doc

@PGDev 已经在评论中说您应该在模型中保存选中/未选中状态。

我希望我的例子对你有所帮助。

您可以在细胞模型中包含细胞状态:

class YourCellModel {

    var task: Task
    var checked: Bool

    init(task: Task, checked: Bool) {
        self.task = task
        self.checked = checked
    }

}

并将其添加到ToDoCell

//...
var model: YourCellModel {
    didSet {
        updateViews()
    }
}

func updateViews() {
    titleLabel.text = task.taskName
    descriptionLabel.text = task.description
    if model.checked {
        //...
    } else {
        //....
    }
}

并在此处更新模型:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: Keys.cell.rawValue, for: indexPath) as! ToDoCell
    // You should contain cell models to remember their states
    let model = cellModels[indexPath.row]
    cell.model = model
    return cell
}

当用户检查一个单元格时,您应该将其保存在您的单元格模型中。你可以这样做ToDoCell

func checked() {
    model.checked = true
}

注意:如果isFiltering为真,则为不同的单元模型数组。

UPD。我注意到你Task的类似于细胞模型。您可以在那里保存checked状态。但是您的手机应该可以访问它。


推荐阅读