我有一个应用程序,我循环一些json并在后台设置一些对象
dispatch_async(CD_QUEUE(), ^{
NSEntityDescription *questionEntity = [NSEntityDescription entityForName:QUESTION inManagedObjectContext:self.backgroundContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]init];
[fetchRequest setEntity:questionEntity];
for (NSInteger i = 0; i < [questionsArray count]; i++) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"uid == %@", questionUID];
[fetchRequest setPredicate:predicate];
NSError *error = nil
NSArray *array = [context executeFetchRequest:fetchRequest error:&error];
MYQuestion *question = nil;
NSLog(@"Error %@",[error localizedDescription]);
if ([array count] == 0)
{
NSLog(@"NIL question");
question = [self newQuestionInContext:context];
question.uid = questionUID;
}
else
question = [array objectAtIndex:0];
if ([questionDataDictionary objectForKey:@"question"] != [NSNull null] && [questionDataDictionary objectForKey:@"question"] != nil)
{
NSLog(@"set question %@",question);
NSLog(@"UID: %@",question.uid);
question.body = [questionDataDictionary objectForKey:@"question"];
NSLog(@"set question finished");
}
and so on....
有时这会在每次为同一个问题设置问题时遇到困难,但有时它会在没有问题的情况下完成。问题不是零,因为你不能看到json对象..所以这里有什么问题?我的应用程序在此时陷入困境,我不知道如何解决这个问题(如果它发生)
...日志
Error (null)
set question < MYQuestion: 0x17515e20> (entity: MYQuestion; id: 0x17641990 <x-coredata://103ACE29-9CF0-4216-BAF8-A30A04C22B0D/MYQuestion/p12493> ; data: < fault >)
因此当我尝试访问此对象的任何属性时出现错误...没有错误提取,但对象有时会出错?我不明白。
答案 0 :(得分:1)
这是一个并发问题。通常,NSManagedObjects
不是线程安全的。这意味着您只能从创建NSManagedObjectContext
的线程或此上下文的专用队列中读取和写入其属性。
您正在CD_QUEUE
访问您的托管对象,因此由Grand Central Dispatch决定此代码将在哪个线程中执行。因此,有可能从“错误”的线程访问这些托管对象 - 而不是他们的context
“生活”的线程。
而不是dispatch_async
,在performBlock
上使用performBlockAndWait
或context
方法之一。它们的目的是确保以安全的方式访问托管对象:
[context performBlock:^{
//do what you did in dispatch_async block
];
如果您想了解有关核心数据和并发性的更多信息,请阅读详细的(虽然有点过时)Apple的Core Data Concurrency Guide和Common Background Practices by objc.io。
对于问题的第二部分:对象为fault
并不意味着在获取请求期间出现错误。这意味着对象的属性尚未从持久性存储(如SQLite数据库)加载到内存中。更多相关内容:Faulting and uniquing