我是获得以下核心数据错误(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互斥锁块包装了对象,但它仍然无法获取该对象。
看来保存上下文之前手动修复了这个问题,但我想要获取对象,无论是否保存它,因为此时不应该保存数据库。
答案 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的对象。
祝你好运:)