项目在 Core Data 中更新后不会在 UI 上更新

问题描述 投票:0回答:1

我在更新核心数据中的项目时遇到 UI 问题。假设我有三个屏幕 A、B 和 C,其中 A --> B --> C。在屏幕 A 上,我有一个 tableView,其中包含来自 Core Data 的项目。在屏幕 C 上,我必须对核心数据的项目进行一些更改,例如更新或删除它们。所以,当我返回屏幕 A 并刷新 tableView 以获取更新列表时,UI 没有更新。

我调试了代码,我可以看到核心数据已正确更新。

您知道问题是什么吗?为什么 UI 没有更新但核心数据是最新的?

ios swift core-data
1个回答
0
投票

您遇到的问题可能与未在主线程上更新 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
© www.soinside.com 2019 - 2024. All rights reserved.