UITableView每次加载时CoreData记录出现重复单元格问题求助
UITableView重复展示CoreData记录问题解决方案
问题根因
代码里的核心问题出在两个地方:
- 存储CoreData查询结果的数组
Rec被定义为全局变量,不会随TableViewController实例销毁而清空 firstLoad是TableViewController的实例属性,每次重新进入页面生成新的VC实例时,firstLoad都会重置为true,触发一次新的CoreData查询,查询到的所有记录会被追加到全局的Rec数组中,导致数组里的记录每次进入页面都翻倍
修复方案
按照以下步骤修改代码即可解决问题:
- 将全局的
Rec数组移到TableViewController类内部,作为私有属性 - 每次执行CoreData查询之前先清空数组,避免旧数据残留
- 可选优化:如果需要每次进入页面都展示最新数据,可以将查询逻辑移到
viewWillAppear中,去掉firstLoad判断,保证每次进入页面都拉取最新全量数据,适配新增、修改、删除后的数据同步需求
修正后的代码示例
import UIKit import CoreData class TableViewController: UITableViewController { // 把Rec数组移到类内部,不再是全局变量 private var Rec = [Records]() // 提前缓存未删除的记录,避免每次计算行数、取cell时重复遍历 private var validRecords: [Records] { Rec.filter { $0.del == nil } } override func viewDidLoad() { super.viewDidLoad() fetchCoreDataRecords() } // 每次进入页面都拉取最新数据 override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) fetchCoreDataRecords() } // 抽取CoreData查询逻辑为独立方法 private func fetchCoreDataRecords() { let appDelegate = UIApplication.shared.delegate as! AppDelegate let context = appDelegate.persistentContainer.viewContext let request = NSFetchRequest<Records>(entityName: "Records") do { // 查询前先清空原有数据,避免累加 Rec.removeAll() // 直接指定结果类型为Records,不需要强转NSArray Rec = try context.fetch(request) tableView.reloadData() } catch { print("Fetch Failed: \(error.localizedDescription)") } } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "myCell") as! TableViewCell let thisrec = validRecords[indexPath.row] cell.idLB.text = thisrec.id cell.nameLB.text = thisrec.name cell.lastLB.text = thisrec.last cell.genderLB.text = thisrec.gender cell.ageLB.text = thisrec.age cell.addressLB.text = thisrec.address return cell } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return validRecords.count } override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){ self.performSegue(withIdentifier: "editNote", sender: self) } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { guard segue.identifier == "editNote", let indexPath = tableView.indexPathForSelectedRow, let recDetail = segue.destination as? AddViewController else { return } recDetail.selectedCell = validRecords[indexPath.row] tableView.deselectRow(at: indexPath, animated: true) } }
内容的提问来源于stack exchange,提问作者Deepankar Rawal
相关产品推荐
相关产品推荐

