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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12050324/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 01:17:11  来源:igfitidea点击:

'Object's persistent store is not reachable...' on main thread

iosxcodeobjectcore-data

提问by Tim

I'm one of the many getting the following Core Data error (133000):

我是许多收到以下核心数据错误 ( 133000) 的人之一:

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

As I've seen all over SO, this is because of Core Data's threading restrictions.
However, I've complied to all the correct threading restrictions, and yet this error is still coming through.

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

I create an NSManagedObject using the below code to perform the function on the main thread:

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

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

This function then creates the object and it's perfectly happy.
Then attempting to fetch the object with [objectContext existingObjectWithID:objectID error:&error]returns nil with the aforementioned error.

这个函数然后创建对象,它非常高兴。
然后尝试获取对象并[objectContext existingObjectWithID:objectID error:&error]返回 nil 并出现上述错误。

I've also wrapped the object fetching with an @synchonized mutex lock block just in case, and yet it is still failing to fetch that object.

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

It appears that saving the context before hand fixes this, however I want to fetch the object regardless as to whether it's saved or not as the DB shouldn't be saved at this point.

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

回答by Tim

Found the answer.
The problem was nothingto do with threading. It was simply because there was already a write happening (Hence why people assume via Occam's Razor that it's a threading issue).

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

The real reason this error shows, is not to do with threading, like the internet says, but because a read/write is already in progress at the same time you're attempting another read/write.

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

[objectContext existingObjectWithID:objectID error:&error]performs I/O on the database in order to guarantee the object that you get back actually does exist. However, in my case, I was already performing a read higher up in the stack.

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

It was attempting to read the parent's children, then attempting to read each child. Where, in fact, I should be using [objectContext objectWithID:objectID]to fetch a faultedobject, and then perform the appropriate I/O once it's required.

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

This is not only the correct way of doing things, it also saves memory by not loading fifty billion child entities when you only wanted the list of them.

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

Hope that helps clarify things for someone!

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

回答by Stanislav Pankevich

I want to share my case, which was related to NSManagedObjectContextDidSaveNotification:

我想分享我的案例,它与 NSManagedObjectContextDidSaveNotification 相关:

I had this problem only in my UnitTests target, in the test cases which involved interaction with Core Data stack.

我只在我的 UnitTests 目标中遇到了这个问题,在涉及与核心数据堆栈交互的测试用例中。

In my configuration of unit tests target each such case is preceded by beforeEachblock having cleanUnitTestsDatabase()macros which performs a removal of Core Data's .sqlite3 file and reinstantiatiates a managed object context and persistent store coordinator to a new fresh state, so I have a whole database in a clean state each time I run in a new/next test case.

在我对单元测试目标的配置中,每个这样的情况都以beforeEach具有cleanUnitTestsDatabase()宏的块为先,这些宏执行删除核心数据的 .sqlite3 文件并将托管对象上下文和持久存储协调器重新实例化为新的新状态,因此我有一个完整的数据库每次我在新的/下一个测试用例中运行时都保持干净状态。

This caused the problem, because sometimes the following method was called after the current database had been axed because the current test case has been already passed and the next following test case has been entered already:

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

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

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

回答by hokkuk

I wanted to show an example of this problem of two reads of the NSManagedObject that will crash into each other and produce the error message in the Original question. but this will happen only if you have the NSManagedObjectContextDidSaveNotification set up, and are doing a mergeChangesFromContextDidSaveNotification... interestingly this notification was firing on a read of a valueForKey... not sure if there is a problem there.

我想展示这个问题的示例,即两次读取 NSManagedObject 会相互碰撞并在原始问题中产生错误消息。但这只会发生在您设置了 NSManagedObjectContextDidSaveNotification 并且正在执行 mergeChangesFromContextDidSaveNotification 时……有趣的是,此通知是在读取 valueForKey 时触发的……不确定那里是否有问题。

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

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

and how i solved it :0)

以及我是如何解决的:0)

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

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

in any case, put in an NSLog and find as many saves as possible, because more than likely you don't need so many saves or reads, and try to get it all into one read or one write.

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

回答by Homero Barbosa

I was getting the same error, though my problem was slightly different. I had multiple NSManagedObjectContexts with different NSPersistentStoreCoordinators (a 3rd party library). They were having conflicts when the NSManagedObjectContextDidSaveNotificationnotification happens. That is, you're notifying one of the NSManagedObjectContexts of changes it doesn't know about. That's what "Object's persistent store is not reachable from this NSManagedObjectContext's coordinator" was saying with different words :)

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

回答by ethoooo

I had the same error & it turns out it was because the temporary child MOC I was using to get object with ID did not have it's parent set to my main MOC.

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

All I ended up needing to do was this.

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

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

And then get objects with IDs if that's your goal.

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

Good luck :)

祝你好运 :)