Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 从UITableView插入/删除单元格后的IndexPath错误 密码_Ios_Swift_Uitableview - Fatal编程技术网

Ios 从UITableView插入/删除单元格后的IndexPath错误 密码

Ios 从UITableView插入/删除单元格后的IndexPath错误 密码,ios,swift,uitableview,Ios,Swift,Uitableview,VC问题部分的要点: // Part of VC where cell is setting func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(for: indexPath) as Cell let cellVM = viewModel.cellVM(

VC问题部分的要点:

// Part of VC where cell is setting
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(for: indexPath) as Cell
    let cellVM = viewModel.cellVM(for: indexPath)

    cell.update(with: cellVM)
    cell.handleDidChangeSelectionState = { [weak self] selected in
        guard
            let `self` = self
        else { return }

        self.viewModel.updateSelectionState(selected: selected, at: indexPath)
    }

    return cell
}

// Part of code where cell can be deleted
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
    let deleteAction = UITableViewRowAction(style: .destructive, title: "delete".localized, handler: { [weak self] _, indexPath in
        guard let self = self else { return }

        self.viewModel.delete(at: indexPath)
        tableView.deleteRows(at: [indexPath], with: .left)
    })

    return [deleteAction]
}
问题 当单元格被删除后,将涉及
handledChangeSelectionState
,然后将
indepath
传递到
viewModel。updateSelectionState
将出错(将等于单元格删除前的值)

我想我知道为什么
  • indepath
    是一个结构,因此
    handledChangeSelectionState
    保留当前值(而不是实例)的副本。原始值的任何更新都不会更新捕获的副本
  • tableView.deleteRows
    不会重新加载tableView的数据源,因此
    cellForRowAt
    不会调用。这意味着
    handledChangeSelectionState
    将不会捕获更新的副本
  • 我的方法是解决这个问题 *第一 询问
    处理的IDChangeSelectionState中的indexPath值:

    cell.handleDidChangeSelectionState = { [weak self, weak cell] selected in
        guard
            let `self` = self,
            let cell = cell,
            // now I have a correct value
            let indexPath = tableView.indexPath(for: cell)
        else { return }
    
        self.viewModel.updateSelectionState(selected: selected, at: indexPath)
    }
    
    *第二 每次删除后执行
    重新加载数据()

    问题 哪种方法更好

    我想:

    • 保持动画流畅(得益于
      tableView.deleteRows(位于:[]
    • 找到更好的性能(我不确定哪一个更优化,
      reloadData()
      indepath(对于单元格:)
    也许有更好的第三种方法


    感谢您的建议。

    只有1st方法满足保持动画平滑的第一个条件。在
    deleteRows
    之后立即调用
    reloadData
    会中断动画


    调用
    indexPath(for:cell)
    肯定比重新加载整个表视图便宜。

    不要使用重新加载特定行,因为删除行时索引已更改,删除行后它将删除动画,这就是为什么需要重新加载
    tableview.reloadData()
    在您的情况下,这是一个更好的选择

    let deleteAction = UITableViewRowAction(style: .destructive, title: "delete".localized, handler: { [weak self] _, indexPath in
            guard let self = self else { return }
    
            self.viewModel.delete(at: indexPath)
            tableView.deleteRows(at: [indexPath], with: .left)
    
            // force to recall `cellForRowAt` then `handleDidChangeSelectionState` will capture correct value
            tableView.reloadData()
        })
    
    let deleteAction = UITableViewRowAction(style: .destructive, title: "delete".localized, handler: { [weak self] _, indexPath in
            guard let self = self else { return }
    
            self.viewModel.delete(at: indexPath)
            tableView.deleteRows(at: [indexPath], with: .left)
    
            // force to recall `cellForRowAt` then `handleDidChangeSelectionState` will capture correct value
            tableView.reloadData()
        })