ios - 在获取 indexPath 之后但在删除该 indexPath 处的单元格之前调用 reloadData() 是否不安全?

标签 ios swift uitableview tableview race-condition

我正在尝试追踪应用程序中的严重崩溃。

我有一些代码可以有效地做到这一点:

if let indexPath = self.tableView.indexPath(for: myTableViewCell) {
    // .. update some state to show a different view in the cell ..
    self.tableView.reloadData()

    // show nice fade out of the cell
    self.friendRequests.remove(at: indexPath.row)
    self.tableView.deleteRows(at: [indexPath], with: .fade)
}

担心的是调用 reloadData() 以某种方式使我刚刚检索到的 indexPath 无效,因此应用程序在尝试删除该 indexPath 处的单元格时崩溃。这可能吗?

编辑:

用户交互是这样的:

  1. 用户点击 TableView 单元格内的按钮 [添加 friend ] <-- indexPath 在此处检索
  2. 将按钮更改为 [已添加] 以显示已收到点击。 <-- 此处调用 reloadData
  3. 在短暂延迟(0.5 秒)后淡出单元格。 <-- 从#1 中使用 indexPath 调用此处删除

我可以更改我的代码以不调用 reloadData 而只是更新单元格的 View 。这是可取的吗?如果我不这样做会发生什么?

最佳答案

就我个人而言,我只是重新加载有问题的按钮 reloadRows(at:with:) ,而不是整个 TableView 。这不仅效率更高,而且如果您还没有滚动到列表顶部,它还可以避免滚动列表时出现不和谐的情况。

然后我会推迟 deleteRows(at:with:)动画的一小部分时间。我个人认为 0.5 秒太长了,因为用户可能会继续点击另一行,如果他们不幸在动画期间的错误时间点击,他们很容易得到与预期不同的行。您希望延迟足够长,以便他们对他们点击的内容得到肯定的确认,但又不会长到产生令人困惑的用户体验。

无论如何,你最终会得到这样的结果:

func didTapAddButton(in cell: FriendCell) {
    guard let indexPath = tableView.indexPath(for: cell), friendsToAdd[indexPath.row].state == .notAdded else {
        return
    }

    // change the button

    friendsToAdd[indexPath.row].state = .added
    tableView.reloadRows(at: [indexPath], with: .none)

    // save reference to friend that you added

    let addedFriend = friendsToAdd[indexPath.row]

    // later, animate the removal of that row

    DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
        if let row = self.friendsToAdd.index(where: { $0 === addedFriend }) {
            self.friendsToAdd.remove(at: row)
            self.tableView.deleteRows(at: [IndexPath(row: row, section: 0)], with: .fade)
        }
    }
}

(注意,我使用 === 是因为我使用的是引用类型。我会使用 == 和符合 Equatable 的值类型 如果处理值类型。但这些是与您的更大问题无关的实现细节。)

产生:

enter image description here

关于ios - 在获取 indexPath 之后但在删除该 indexPath 处的单元格之前调用 reloadData() 是否不安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42984732/

相关文章:

ios - InsertRowsAtIndexPaths 错误 swift

ios - 有两个选择的数组让我只完成了一半

c++ - 如何使用 Swift 代码调用的线程在 C++ 上创建异步调用函数?

ios - 您设置的约束是否保证 100% 的时间都有效?

ios - 无法在 cellForRowAtIndexPath 中设置单元格 alpha

iPhone - 检测 UITableViewCell subview 上的触摸

ios - Bot 找不到配置文件,尽管项目包含它并且已上传到 bot 服务器

ios - 在 ios 中将图像转换为卡通

ios - 如何从电话号码字符串中确定地区?

ios - 使用 Swift 更新 UITableViewCell 中的 UILabel 而无需刷新整个页面