如何对TableView单元格排序?现有实现失效问题排查
排查TableView单元格排序失效的常见问题
嗨,我来帮你捋捋TableView排序功能失效的问题!这种情况我踩过好几次坑,大概率是以下几个环节没处理到位,咱们一个个排查:
数据源数组的可变性质与赋值问题
首先,你用来给TableView提供数据的数组必须是var声明的可变数组,用let声明的不可变数组排序后根本无法修改内容。另外,sorted()方法会返回一个新数组,你必须把这个新数组重新赋值给你的数据源变量,而不是只调用方法:// 错误:仅调用sorted但未赋值,原数组毫无变化 myDataArray.sorted { $0.name < $1.name } // 正确:将排序后的新数组赋值回数据源 myDataArray = myDataArray.sorted { $0.name < $1.name }排序后未通知TableView刷新UI
就算数据源数组已经排好序,TableView不会自动感知数据变化!必须在排序完成后调用tableView.reloadData()(或者更精细化的刷新方法),比如你的@IBAction应该是这样:@IBAction func sortButtonTapped(_ sender: UIButton) { // 1. 排序数据源 myDataArray = myDataArray.sorted { $0.yourTargetProperty < $1.yourTargetProperty } // 2. 强制TableView刷新显示 tableView.reloadData() }这是最容易遗漏的步骤,很多时候数组已经排好序,但UI还是老样子,就是因为忘了这行代码。
cellForRowAt方法的数据源引用错误
检查你在cellForRowAt indexPath方法里,是不是真的用了排序后的数据源数组给单元格赋值?比如有没有不小心引用了原始的未排序数组,或者索引对应错误:// 正确:使用更新后的数据源数组 let item = myDataArray[indexPath.row] cell.titleLabel.text = item.title // 错误:误用了未排序的原始数组 let item = originalUnSortedArray[indexPath.row]排序逻辑本身存在问题
有时候排序代码看似没问题,但逻辑上有疏漏:- 字符串排序时忽略大小写:如果需要不区分大小写排序,要用
localizedCaseInsensitiveCompare而不是直接用<myDataArray = myDataArray.sorted { $0.name.localizedCaseInsensitiveCompare($1.name) == .orderedAscending } - 数字排序误用字符串比较:如果按数值排序,别把数字转成字符串再比较,直接用数值的
</>即可,否则会出现"10"排在"2"前面的错误。
- 字符串排序时忽略大小写:如果需要不区分大小写排序,要用
Diffable Data Source的特殊处理
如果你用的是iOS 13+的UITableViewDiffableDataSource,那么直接调用reloadData可能不生效,需要重新生成Snapshot并应用:var snapshot = NSDiffableDataSourceSnapshot<YourSectionType, YourItemType>() snapshot.appendSections([.main]) snapshot.appendItems(myDataArray) dataSource.apply(snapshot, animatingDifferences: true)
你可以按照这个顺序逐一排查,大概率能找到问题所在!
内容的提问来源于stack exchange,提问作者Ivan Kisin
相关产品推荐
相关产品推荐

