OStack程序员社区-中国程序员成长平台

标题: ios - 在后台同步的同时在 UI 交互上操作 Core Data Context 的最佳实践 [打印本页]

作者: 菜鸟教程小白    时间: 2022-12-11 19:09
标题: ios - 在后台同步的同时在 UI 交互上操作 Core Data Context 的最佳实践

我已经研究了很多关于如何使用 NSManagedObjectContext 的文章和讨论,但仍然无法为我的项目找到令人满意的架构。

在我的应用程序中,可以从三个来源修改数据,当同时发生冲突时按优先级排序(例如,云的优先级最低):

  1. 用户界面,
  2. BLE 消息,
  3. 来自云端的 HTTP 响应

由于我仍然不是 iOS 开发方面的专家,因此我尽量避免为每个源使用多个上下文。然而,经过数周的反复试验,我很不情愿,但开始考虑是否真的需要采用多上下文方法。

一开始,我尝试在主上下文上使用 context.perform { } 来做所有的数据更改操作(add/update/delete,除了获取)。我将 fetch 保持为同步功能,因为我希望数据获取是即时的,以便可以响应 UI。但是,在这种方法下,我偶尔会收到 "Collection <__NSCFSet: 0x000000000> was mutated while being enumerated" 异常(我想这可能发生在 forEach map 函数用于批量数据处理)。我还发现,当后台队列中有大量记录要更新时,这种方法仍然会阻塞 UI。

因此,我创建了一个后台上下文并使用父子模型来操作数据。基本上主上下文(父)只负责获取数据,而后台上下文(子)通过 backgroundContext.perform { }< 操作所有数据更改(添加/更新/删除)/。这种方法解决了 UI 阻塞问题,但是偶尔会出现 collection mutated 错误,并且在这种结构下还会出现另一个问题:例如,当我在 ViewController A 中添加一条数据记录并移动到 View Controller B 时,应用程序会崩溃,这即使后台上下文尚未完成添加数据记录,也会立即获取相同的数据。

因此,我想就我的项目中使用 Core Data 提出一些建议。在我的父子数据上下文模型下我做错了什么吗?或者,我应该不可避免地选择一个没有父子的真正的多上下文模型吗?怎么做?

我的主要上下文(父)和背景上下文(子)是这样启动的:

lazy var _context: NSManagedObjectContext = {
        return (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    }()

lazy var _backgroundContext: NSManagedObjectContext = {
    let ctx = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.privateQueueConcurrencyType)
    ctx.parent = self._context
    return ctx
}()

合并函数如下:

@objc func contextDidSaveContext(notification: NSNotification) {
    let sender = notification.object as! NSManagedObjectContext

    if sender === self._context {
        NSLog("******** Saved main Context in this thread")
        self._backgroundContext.perform {
            self._backgroundContext.mergeChanges(fromContextDidSave: notification as Notification)
        }
    } else if sender === self._backgroundContext {
        NSLog("******** Saved background Context in this thread")
        self._context.perform {
            self._context.mergeChanges(fromContextDidSave: notification as Notification)
        }
    }
    else {
        NSLog("******** Saved Context in other thread")
        self._context.perform {
            self._context.mergeChanges(fromContextDidSave: notification as Notification)
        }
        self._backgroundContext.perform {
            self._backgroundContext.mergeChanges(fromContextDidSave: notification as Notification)
        }
    }
}

任何关于核心数据结构的建议都将不胜感激。



Best Answer-推荐答案


您是否探索过使用 NSFetchedResultsController 来获取数据? NSFetchedResultsController 提供了一种线程安全的方式来观察由于 CoreData 中的创建、更新或删除操作而导致的数据变化。 使用 NSFetchedResultsController 的委托(delegate)方法来更新 UI。 理想情况下,controllerDidChangeContent 委托(delegate)会给你一个更新 UI 的指示。 Documentation for reference

关于ios - 在后台同步的同时在 UI 交互上操作 Core Data Context 的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47027771/






欢迎光临 OStack程序员社区-中国程序员成长平台 (https://ostack.cn/) Powered by Discuz! X3.4