核心数据并发



我想得到一些关于在我的项目中使核心数据操作并发的建议。我的项目已经运行了两年,因此它有许多实现,可以根据objectiveC中新功能的可用性进行优化。我主要是在寻求优化CoreData操作。

目前,大多数数据操作都是使用主托管对象上下文来完成的。最近,我实现了一个新功能,可以下载一大组数据,并在登录后使用核心数据插入数据库。这应该与应用程序中的其他操作并行执行。现在我意识到为核心数据编写的代码是在主线程中执行的,因为在coredata操作期间应用程序的UI是阻塞的。因此,我参考了许多博客,了解到有两种策略可以实现核心数据并发,即借助多个上下文的通知和父/子托管对象上下文。

我尝试了父母/孩子策略,因为苹果不喜欢其他策略。但我遇到了随机崩溃,executeFetchRequest上出现了异常"Collection was mutated while be enumerated"。此异常在实现父/子策略之后开始发生。有人能帮我解决这个问题吗?

是的,我知道并没有那么多博客描述项目中核心数据的有效使用,但幸运的是我找到了一个。。。正确地指出了你的问题。。。查看此处->https://medium.com/soundwave-stories/core-data-cffe22efe716#.3wcpw1ijo

同样,您的异常也发生了,因为您正在更新数据库,而它正在某个地方被用来删除此异常,您可以这样做:

如果您正在数组或字典中获取数据,那么请像下面这样更改语句

NSDictionary *myDict = [[coreDataDectionary] mutableCopy];

现在,对从数据库中获取的数组或字典执行任何操作,它都不会显示任何异常。希望这对你有帮助。

试试这个:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL), ^{
    // DATA PROCESSING 
    dispatch_async(dispatch_get_main_queue(), ^{
        // UPDATE UI
    });
}

您应该在代码中使用completionBlock。这是教程和解释。它将允许你不冻结你的UI应用程序,即使你的下载还没有完成。即使块内的代码尚未完成,代码的执行也将继续。下载结束后,块内会有一个回调操作。

在导入大型数据集时,使用此核心数据堆栈来最小化UI锁定:

  1. 一个主线程MOC及其自己的PSC
  2. 一个具有自己PSC的后台主运行中心
  3. 在后台MOC的保存通知中将更改合并到主线程MOC中

是的,您可以也应该使用指向同一.sqlite文件的两个独立PSC(NSPersistentStoreCoordinator)。它将把整个锁定时间减少到只有SQLite锁,避免PSC级别的锁,所以整个UI锁定时间将是[SQLite写锁]+[主线程MOC读]。

您可以在后台线程中将后台MOC与NSConfinementConcurrencyType一起使用,甚至可以在NSOperation中更好地使用——我发现在同一线程上处理数据并将其提供给核心数据非常方便。

批量导入。根据经验选择批量大小。每次保存后重置后台MOC。

当处理具有数十万对象的大型数据集时,不要在每次保存时都将refreshObject:mergeChanges:与主线程MOC一起使用。它很慢,最终会消耗掉所有可用内存。请重新加载您的FRC。

关于"集合在枚举时发生了变异"。核心数据中的许多关系都是可变的集合,所以在迭代之前,您必须制作一个副本,或者更好地将它们排序为NSArrays。

最新更新