主线程上'对象的持久存储无法访问...'

时间:2012-08-21 07:43:13

标签: ios xcode object core-data

我是获得以下核心数据错误(133000)的众多错误之一:

Object's persistent store is not reachable from this NSManagedObjectContext's coordinator

正如我所看到的那样,这是因为Core Data的线程限制 但是,我已经遵守了所有正确的线程限制,但这个错误仍然存​​在。

我使用以下代码创建NSManagedObject以在主线程上执行该功能:

NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
                                                                        selector:@selector(commitPlayer:)
                                                                          object:message];
[[NSOperationQueue mainQueue] addOperation:operation];
[operation release];

此功能然后创建对象,它非常高兴 然后尝试使用[objectContext existingObjectWithID:objectID error:&error]获取对象,返回上述错误的nil。

为了以防万一,我还使用@synchonized互斥锁块包装了对象,但它仍然无法获取该对象。

看来保存上下文之前手动修复了这个问题,但我想要获取对象,无论是否保存它,因为此时不应该保存数据库。

5 个答案:

答案 0 :(得分:13)

找到答案。
问题是 没有 与线程有关。这只是因为已经发生了写作(因此人们为什么通过Occam的Razor认为这是一个线程问题)。

这个错误显示的真正原因与线程无关,就像互联网所说,但是因为在你尝试另一次读/写的同时读/写已经在进行中。

[objectContext existingObjectWithID:objectID error:&error]在数据库上执行I / O,以保证您获得的对象确实存在。 然而 ,在我的情况下,我已经在堆栈中执行了更高的读取

它试图阅读父母的孩子,然后尝试阅读每个孩子。实际上,我应该使用[objectContext objectWithID:objectID]来获取故障对象,然后在需要时执行相应的I / O.

这不仅是正确的做事方式,还可以通过在您只需要列表时加载500亿个子实体来节省内存。

希望有助于为某人澄清事情!

答案 1 :(得分:5)

我想分享我的案例,这与NSManagedObjectContextDidSaveNotification有关:

我在UnitTests目标中遇到此问题,在涉及与Core Data堆栈交互的测试用例中。

在我的单元测试配置目标中,每个此类案例前面都有beforeEach块,其中包含cleanUnitTestsDatabase()个宏,这些宏执行Core Data的.sqlite3文件的删除,并重新实例化托管对象上下文和持久性存储协调器一个新的状态,所以每次我在新的/下一个测试用例中运行时,我都有一个处于干净状态的整个数据库。

这导致了这个问题,因为有时在当前数据库被砍掉之后调用了以下方法,因为当前测试用例已经通过并且已经输入了下一个测试用例:

- (void)managedObjectContextDidSaveNotification:(NSNotification *)notification {
    NSManagedObjectContext *savedContext = [notification object];

    if ([savedContext isEqual:self.mainQueueManagedObjectContext] == NO) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.mainQueueManagedObjectContext mergeChangesFromContextDidSaveNotification:notification];
        });
    }
}

答案 2 :(得分:2)

我想展示两个NSManagedObject读取问题的示例,这两个读取将相互崩溃并在原始问题中产生错误消息。但是只有当你设置了NSManagedObjectContextDidSaveNotification并且正在进行mergeChangesFromContextDidSaveNotification时才会发生这种情况......有趣的是,这个通知是在读取valueForKey时触发的...不确定那里是否存在问题。

    NSArray *theEvents = nil;
NSError *error = nil;

if ([currentObject valueForKey:@"event58Identifier"]) theEvents = [eventStore calendarItemsWithExternalIdentifier:[currentObject valueForKey:@"event58Identifier"]];

以及我如何解决它:0)

    NSArray *theEvents = nil;
NSError *error = nil;
NSString * identEvent = [currentObject valueForKey:@"event56Identifier"];

if (identEvent) theEvents = [eventStore calendarItemsWithExternalIdentifier:identEvent];

在任何情况下,放入一个NSLog并找到尽可能多的保存,因为很可能你不需要这么多的保存或读取,并尝试将它们全部放入一次读取或一次写入。

答案 3 :(得分:1)

虽然我的问题略有不同,但我得到了同样的错误。我有多个NSManagedObjectContext个不同的NSPersistentStoreCoordinator s(第三方库)。 NSManagedObjectContextDidSaveNotification通知发生时,他们发生冲突。也就是说,您正在通知NSManagedObjectContext其中一个不知道的更改。这就是“从这个NSManagedObjectContext的协调器无法访问对象的持久存储”这句话用不同的词语说:)

答案 4 :(得分:0)

我遇到了同样的错误,事实证明这是因为我用来获取ID为ID的对象的临时子MOC没有将其父对象设置为我的主MOC。

我最后要做的就是这个。

let tmpContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
tmpContext.parent = CoreDataStack.context

如果这是您的目标,则获取具有ID的对象。

祝你好运:)