12

我是众多收到以下核心数据错误 ( 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 互斥锁块包装了对象获取,但它仍然无法获取该对象。

似乎事先保存上下文可以解决这个问题,但是我想获取对象,无论它是否已保存,因为此时不应保存数据库。

4

5 回答 5

15

找到了答案。
问题与线程无关。这仅仅是因为已经发生了写入(因此人们通过奥卡姆剃刀假设这是一个线程问题)。

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

[objectContext existingObjectWithID:objectID error:&error]对数据库执行 I/O 以保证您返回的对象确实存在。但是,就我而言,我已经在堆栈中执行了更高的读取操作。

它试图阅读父母的孩子,然后尝试阅读每个孩子。事实上,我应该在哪里[objectContext objectWithID:objectID]获取错误对象,然后在需要时执行适当的 I/O。

这不仅是正确的做事方式,而且当您只需要它们的列表时,它通过不加载 500 亿个子实体来节省内存。

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

于 2012-08-22T06:19:20.897 回答
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];
        });
    }
}
于 2013-09-22T12:57:13.277 回答
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 并找到尽可能多的保存,因为很可能您不需要这么多保存或读取,并尝试将其全部用于一次读取或一次写入。

于 2013-03-13T21:52:29.520 回答
1

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

于 2013-01-23T21:25:03.387 回答
1

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

我最终需要做的就是这个。

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

如果这是您的目标,然后获取带有 ID 的对象。

祝你好运 :)

于 2019-04-16T20:01:21.870 回答