Core Data 后台排序

Posted

技术标签:

【中文标题】Core Data 后台排序【英文标题】:Core Data background sorting 【发布时间】:2011-11-08 15:05:01 【问题描述】:

我有一个Department 实体,它与Employee 实体具有一对多关系。在运行时,对于每个Department 对象,我想维护一个Employee 对象的排序数组(根据某些属性排序),它将用作各种视图对象中的模型。

从我读到的有两种方式来表示排序数组:

Rep1:在Department中定义一个获取的属性(排序由Core Data完成);

Rep2:在Department中维护一个实例变量sortedEmployeesNSArray of Employee objects)(排序由我的代码完成)。

现在我真正的问题是,当应用程序启动时,我有大量的 DepartmentsEmployees 要从持久存储中获取。我想在后台执行排序,以免阻塞 UI。

我尝试了几种方法,但都无济于事:

Method1(使用Rep1):在后台线程中(使用NSOperationQueue),获取所有Departments,然后执行每个获取的属性。然后回到主线程,在主线程的托管对象上下文(MOC)中找到对应的Department对象(通过NSManagedObjectID)并使用fetched属性。 Method1的问题:即使后台Department的fetch完成后,主线程Department对象中的fetched属性也没有填充,这意味着它在主线程Department中重新获取!这违背了后台获取的全部目的。我假设一个获取的属性一旦被获取,就存在于所有 MOC 中,我错了吗?

Method2(使用Rep2):在后台线程中(使用NSOperationQueue),获取所有Departments,然后计算每个sortedEmployees数组。然后回到主线程,在主线程的MOC(通过NSManagedObjectID)中找到对应的Department对象,将上述数组设置为这个对象 . 方法 2 的问题:sortedEmployees 数组中的对象是属于后台线程的 MOCEmployee 对象。当主线程稍后尝试访问它们时,会发生类似"NSManagedObject with ID ... has been invalidated." 的崩溃,这是因为每个线程都必须有自己的 MOC(及其关联的托管对象)。

如果托管对象不能跨线程边界存在,那么如何在后台对托管对象进行排序呢?我错过了什么吗?

【问题讨论】:

【参考方案1】:

庇护,

你没有错过任何东西。您只需要将排序后的数组转换为新的 MOC。这是一个片段:

NSMutableArray *ma = [NSMutableArray arrayWithCapacity: array.count];

for (mo in array) 

    [ma addObject: [moc objectWithID: mo.objectID]];

return ma;

这将迁移您的阵列。据我了解,这是一个有效的过程。此外,您可以依赖行缓存来对属性进行高性能访问。

安德鲁

【讨论】:

谢谢。您能否根据行缓存详细说明您的意思?什么行缓存? 另外,我应该在哪个线程中执行上述数组迁移?在主线程的情况下,当您访问 mo.objectID 时,“mo”是否会失效并因此出错?在后台线程的情况下,访问[moc objectWithID:...]会不会有问题,因为moc属于主线程? Pius,行缓存由持久存储协调器维护。这是一种自动性能优化。你不需要维护它——Core Data 会。当我在目标线程上时,我通常会转换 ID。安德鲁 P.S.如果您喜欢这个答案,请记得选择它作为“正确”答案。

以上是关于Core Data 后台排序的主要内容,如果未能解决你的问题,请参考以下文章

使用 Core Data 进行排序的 fetchRequest 有啥限制?

Core Data 中的排序顺序具有多重关系

如何根据来自多个 Core Data 属性的计算值进行排序

在 Swift Core Data 中对存储的数据模型提取进行排序

在 Swift 中从 Core Data 接收到的排序数组

在 SwiftUI 中将 @FetchRequest 与 Core Data 一起使用时修改 nil 排序行为