我在更新核心数据中的项目时遇到 UI 问题。假设我有三个屏幕 A、B 和 C,其中 A --> B --> C。在屏幕 A 上,我有一个 tableView,其中包含来自 Core Data 的项目。在屏幕 C 上,我必须对核心数据的项目进行一些更改,例如更新或删除它们。所以,当我返回屏幕 A 并刷新 tableView 以获取更新列表时,UI 没有更新。
我调试了代码,我可以看到核心数据已正确更新。
您知道问题是什么吗?为什么 UI 没有更新但核心数据是最新的?
您遇到的问题可能与未在主线程上更新 UI 或未刷新 tableView 的数据源有关。这是确保您的 UI 得到正确更新的分步过程:
使用 NSFetchedResultsController:如果您还没有使用它,请考虑使用 NSFetchedResultsController 来管理您的 tableView 的核心数据获取结果。它会自动监控数据的变化并更新 tableView。
观察核心数据变化:通过使用 NSFetchedResultsController 或通过将观察者添加到 NSManagedObjectContextObjectsDidChange 或 NSManagedObjectContextDidSave 等通知中,确保您正在观察核心数据对象的变化。
在主线程上更新用户界面:确保你在主线程上更新用户界面。您可以使用 DispatchQueue.main.async { } 来更新 UI。
刷新 tableView:更新数据源后,确保调用 tableView.reloadData() 刷新 UI。
这里是一个如何使用 NSFetchedResultsController 来更新你的 tableView 的例子:
首先,在您的视图控制器中,声明一个 NSFetchedResultsController 实例并符合其委托:
import UIKit
import CoreData
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, NSFetchedResultsControllerDelegate {
@IBOutlet weak var tableView: UITableView!
var fetchedResultsController: NSFetchedResultsController<Item>!
// Your other code goes here
}
然后,创建一个函数来设置 NSFetchedResultsController:
func setupFetchedResultsController() {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let fetchRequest: NSFetchRequest<Item> = Item.fetchRequest()
let sortDescriptor = NSSortDescriptor(key: "attribute", ascending: true) // Replace "attribute" with your sort key
fetchRequest.sortDescriptors = [sortDescriptor]
fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
fetchedResultsController.delegate = self
do {
try fetchedResultsController.performFetch()
} catch {
print("Error fetching data: \(error)")
}
}
在viewDidLoad()方法中调用setupFetchedResultsController():
override func viewDidLoad() {
super.viewDidLoad()
setupFetchedResultsController()
}
实现 NSFetchedResultsControllerDelegate 方法来处理数据变化:
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.beginUpdates()
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
switch type {
case .insert:
tableView.insertRows(at: [newIndexPath!], with: .automatic)
case .delete:
tableView.deleteRows(at: [indexPath!], with: .automatic)
case .update:
tableView.reloadRows(at: [indexPath!], with: .automatic)
case .move:
tableView.moveRow(at: indexPath!, to: newIndexPath!)
@unknown default:
fatalError("Unknown change type")
}
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.endUpdates()
}
确保您的 tableView(_:cellForRowAt:) 方法使用 NSFetchedResultsController 来填充单元格:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ItemCell", for: indexPath)
let item = fetchedResultsController.object(at: indexPath)
// Configure