Realm填充的TableView删除单元格后,最后单元格跳转至被删位置求助
问题原因及解决方案
这个问题我做Realm+UITableView开发时也碰到过,核心原因是你用了tableView.reloadData()全量刷新列表,再加上Realm Results的自动更新特性,导致TableView无法正确处理单元格的位置动画,才出现最后一个单元格跳转到被删除位置的奇怪现象。
具体原因拆解:
- Realm Results的自动更新特性:你通过
realm.objects(Times.self)获取的Results是一个实时自动同步的集合,当你删除其中的对象后,这个集合会自动更新,根本不需要手动调用loadTimes()去重新获取数据,你的loadTimes()方法反而会强制TableView重新加载所有数据,打乱了它的状态管理。 - 全量刷新的弊端:
tableView.reloadData()会让TableView直接重置所有单元格,它无法感知到具体是哪一行被删除,所以在重新渲染时会出现位置计算错误,导致最后一个单元格“跳”到被删除的位置。
修复方案(修改你的代码):
只需要调整tableView(_:commit:forRowAt:)方法,移除loadTimes()的调用,改用UITableView的批量删除API来处理:
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { if editingStyle == .delete { // 先执行Realm数据删除 self.updateModel(at: indexPath) // 通知TableView精确删除对应行,使用系统动画过渡 tableView.deleteRows(at: [indexPath], with: .automatic) } } // 保留你的updateModel方法,不需要改动 func updateModel(at indexpath: IndexPath) { if let itemForDeletion = results?[indexpath.row] { do{ try self.realm.write { self.realm.delete(itemForDeletion) } } catch { print("Error saving context \(error)") } } } // 可以移除loadTimes()方法,或者只在初始化时调用一次(比如viewDidLoad里)
额外注意事项:
- 确保你的
results是类级别的属性,这样才能保持和Realm数据库的实时绑定,数据变化时它会自动更新。 - 如果后续需要监听
Results的其他变化(比如其他页面修改了数据),可以使用Realm的NotificationToken来监听集合变化,然后再针对性地更新TableView,而不是全量刷新。
内容的提问来源于stack exchange,提问作者M. Gabriel
相关产品推荐
相关产品推荐

