Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/97.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 使用NSThread和core数据时出现问题,更改未正确写入_Ios_Core Data - Fatal编程技术网

Ios 使用NSThread和core数据时出现问题,更改未正确写入

Ios 使用NSThread和core数据时出现问题,更改未正确写入,ios,core-data,Ios,Core Data,我有一个问题,我就是想不出解决办法 我的应用程序配置为使用核心数据(使用xCode创建的AppDelegate中的templatecode),在后台线程中导入大量数据。问题是,如果我运行了大型导入,我在UI线程中对核心数据所做的所有更改(有时)都不会保存到存储中。如果我没有运行导入,并且问题不一致,所有数据都会正确保存,这是一个开/关问题,但我已经跟踪到导致问题的导入 我的线程代码如下所示(简化) persistentStoreCoordinator(从现在开始的PSC)是来自应用程序AppDe

我有一个问题,我就是想不出解决办法

我的应用程序配置为使用核心数据(使用xCode创建的AppDelegate中的templatecode),在后台线程中导入大量数据。问题是,如果我运行了大型导入,我在UI线程中对核心数据所做的所有更改(有时)都不会保存到存储中。如果我没有运行导入,并且问题不一致,所有数据都会正确保存,这是一个开/关问题,但我已经跟踪到导致问题的导入

我的线程代码如下所示(简化)

persistentStoreCoordinator(从现在开始的PSC)是来自应用程序AppDelegate的PSC,我认为这就是问题所在。我了解到多线程应该使用单独的PSC,但是如何创建PSC并将其与AppDelegate模板代码中创建的核心数据文件一起分配

导入后核心数据的读取工作正常,但当我稍后将核心数据模型中的一个“文档”实体标记为我的最爱时,即使我从AppDelegate调用save on my context,此更改也不会写入数据库

我认为全局PSC用于同步多个上下文,我的应用程序中的一个上下文,线程导入代码中的导入上下文

如何确保导入代码和UI代码看到相同的更改,以及我的存储一致

多谢各位


/Jacob

他们改进了iOS 5/MacOS 10.7中多线程的工作方式。现在,多线程核心数据有三种模式:
NSConfinementConcurrencyType
NSPrivateQueueConcurrencyType
NSMainQueueConcurrencyType
。第一个是过去的工作方式,也是你正在使用的方式。我之所以提到其他的,是因为它们可能值得研究,也因为这些术语在搜索时可能很有用

对于线程限制方法,您可以像现在这样为每个线程创建一个新的托管对象上下文。我认为在循环之后,您正在后台上下文中调用
save
。您缺少的步骤是响应
NSManagedObjectContextDidSaveNotification
。来自苹果的:

通常,在线程A上注册托管对象上下文保存通知,
NSManagedObjectContextDidSaveNotification
。当您收到通知时,其用户信息字典包含在线程B上插入、删除和更新的托管对象的数组。但是,由于托管对象与不同的线程关联,因此您不应直接访问它们。相反,您将通知作为参数传递给
mergeChangesFromContextDidSaveNotification:
(发送到线程A上的上下文)。使用此方法,上下文能够安全地合并更改

总之,您要做的是订阅该通知,当它发生时(并且调用了选择器),您只需在主线程的托管对象上下文上调用
mergeChangesFromContextDidSaveNotification:
,将通知对象传递给后一种方法,如下所示:

- (void)mergeChanges:(NSNotification *)notification 
{
    if (notification.object != self.context) {
        [self.context mergeChangesFromContextDidSaveNotification:notification];
    }

    return;
}
假设您已经订阅了通知,
self.context
引用了主线程的托管对象上下文。这应该可以处理更新


我在上面提到其他并发类型的原因是,执行并发的另一种方法(如果您使用的是最新的操作系统)涉及父上下文和子上下文。您可以让一个上下文在私有队列模式下运行,并将其父级设置为您的主MOC。当上下文有父上下文时,子上下文上的保存操作只将其更改推送到父上下文,而不接触磁盘。这可能是您可以研究的另一种模式。

他们改进了iOS 5/MacOS 10.7中多线程的工作方式。现在,多线程核心数据有三种模式:
NSConfinementConcurrencyType
NSPrivateQueueConcurrencyType
NSMainQueueConcurrencyType
。第一个是过去的工作方式,也是你正在使用的方式。我之所以提到其他的,是因为它们可能值得研究,也因为这些术语在搜索时可能很有用

对于线程限制方法,您可以像现在这样为每个线程创建一个新的托管对象上下文。我认为在循环之后,您正在后台上下文中调用
save
。您缺少的步骤是响应
NSManagedObjectContextDidSaveNotification
。来自苹果的:

通常,在线程A上注册托管对象上下文保存通知,
NSManagedObjectContextDidSaveNotification
。当您收到通知时,其用户信息字典包含在线程B上插入、删除和更新的托管对象的数组。但是,由于托管对象与不同的线程关联,因此您不应直接访问它们。相反,您将通知作为参数传递给
mergeChangesFromContextDidSaveNotification:
(发送到线程A上的上下文)。使用此方法,上下文能够安全地合并更改

总之,您要做的是订阅该通知,当它发生时(并且调用了选择器),您只需在主线程的托管对象上下文上调用
mergeChangesFromContextDidSaveNotification:
,将通知对象传递给后一种方法,如下所示:

- (void)mergeChanges:(NSNotification *)notification 
{
    if (notification.object != self.context) {
        [self.context mergeChangesFromContextDidSaveNotification:notification];
    }

    return;
}
假设您已经订阅了通知,
self.context
引用了主线程的托管对象上下文。这应该可以处理更新

我在上面提到其他并发类型的原因是另一种并发方法(如果您使用的是最新的操作系统)涉及paren