使用 GCD 时核心数据实体出错

Posted

技术标签:

【中文标题】使用 GCD 时核心数据实体出错【英文标题】:Core Data entities faulting when using GCD 【发布时间】:2014-04-11 18:16:59 【问题描述】:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^

            for (NSDictionary* info in houses) 
                House* house = [DataManager processJSON:info]; //this method processes JSON into Core Data objects and saves them
                [self.data addObject:house];
            

            dispatch_async(dispatch_get_main_queue(), ^
                //update the UI based on the new House objects added to the data array

            );

        );

My House 对象有时会起作用,但通常会出人意料地以这样的方式结束:

<House: 0x17f8b420> (entity: House; id: 0x17f71e90 <x-coredata://2826DE3A-1762-4958-8402-541D2B1754FA/House/p219> ; data: <fault>)

我相信这与在后台线程上处理 Core Data 对象有关,从而导致某种上下文冲突。但是我找不到很多将 Core Data 与 GCD 结合使用的具体示例。关于我可以在此处添加什么以确保对象没有故障的任何建议?

【问题讨论】:

你的主线程上下文是后台线程的父上下文吗?如果是这样,您需要保存后台线程上下文,以便将更改传播到父主上下文。 这个问题是否仅限于打印对象?如果您的代码尝试访问其中一个属性值,它们是否可用? 【参考方案1】:

一般来说,您不应使用任意队列来调度访问特定托管对象上下文和可能托管对象的 Core Data 方法。

一个特定的托管对象上下文与任一相关联

一个专用线程(NSConfinementConcurrencyType) 一个私有调度队列 (NSPrivateQueueConcurrencyType) 主线程 (NSMainQueueConcurrencyType)。

如果您的托管对象上下文是使用NSConfinementConcurrencyType 并发策略创建的,您需要记住您创建上下文的线程并使用该线程将消息发送到上下文,并将消息发送到注册的托管对象这个上下文。

如果上下文是使用NSMainQueueConcurrencyType 并发策略创建的,您需要确保发送到上下文的消息和为此上下文注册的托管对象将在主线程上执行。 p>

如果上下文是使用NSPrivateQueueConcurrencyType 创建的,您需要确保发送到上下文并发送到在此上下文中注册的托管对象的消息将通过使用托管对象上下文的方法performBlock: 在此私有调度队列上执行或preformBlockAndWait:

这对基本上所有 方法都有效——尤其是访问托管对象的属性。只有少数例外,方法可以在任何地方执行,而与并发策略无关,例如[NSManagedObject] objectID .

【讨论】:

以上是关于使用 GCD 时核心数据实体出错的主要内容,如果未能解决你的问题,请参考以下文章

将数据提取到 uipickerview 时出错?

在 SwiftUI 主体中出错的子上下文上创建核心数据实体

Swift Core Data - 使用 NSManagedObject 子类访问获取的实体时出错

csharp 使用实体框架创建数据库时出错

使用核心数据时出错

使用 javax.persistence.EntityManager 将实体添加到我的 SQL 数据库时出错