我是Core Data的新手,我查看过许多与Cored Data相关的问题,但我无法完全理解Core Data和并发的整个概念。似乎有一种方法可以做到这一点,但近年来它发生了变化,现在有点难以过滤哪些信息是最新的,哪些不是。
我正在开发一个小应用程序,它从Web服务导入商店数据,将其呈现给用户并监视用户何时进入特定商店的区域。
我正在使用两个NSManagedObjectContext
,它们是CoreDataHelper
类的一部分。这是init
{/ 1}}实现为单身:
CoreDataHelper
我使用_ - (id)init {
self = [super init];
if (!self) {return nil;}
_model = [NSManagedObjectModel mergedModelFromBundles:nil];
_coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:_model];
_parentContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_parentContext performBlockAndWait:^{
[_parentContext setPersistentStoreCoordinator:_coordinator];
[_parentContext setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
}];
_context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_context setParentContext:_parentContext];
[_context setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
return self;
}
向用户展示数据,使用context
导入和同步背景数据。
我的问题是,当用户输入区域并调用_parentContext
时,我使用以下方法检索此区域中商店的didEnterRegion
NSManagedObject
然而,有时候,并非总是如此,获取请求找不到具有给定ID的商店,即使它在那里是100%。出现这个问题的事实有时会让我得出结论,这与并发性有关。此外,我认为这可能与我在此处使用相同的- (Shop*)findShopWithID:(NSString*)shopID
{
NSArray* fetchedObjects;
NSManagedObjectContext* context = [self getBackgroundManagedObectContext];
if(context==nil)
[self sendRemoteLog:@"Context is nil"];
NSFetchRequest* fetch = [[NSFetchRequest alloc] init];
NSEntityDescription* entityDescription = [NSEntityDescription entityForName:@"Shop" inManagedObjectContext:context];
[fetch setEntity:entityDescription];
[fetch setPredicate:[NSPredicate predicateWithFormat:@"shopID==%@", shopID]];
NSError* error = nil;
fetchedObjects = [context executeFetchRequest:fetch error:&error];
if ([fetchedObjects count] == 1)
return [fetchedObjects objectAtIndex:0];
else
{
[self sendRemoteLog:[NSString stringWithFormat:@"No object found for ID %@",shopID]];
return nil;
}
}
- (NSManagedObjectContext*)getBackgroundManagedObectContext
{
CoreDataHelper* cdh = [(AppDelegate*)[[UIApplication sharedApplication] delegate] cdh];
return [cdh backgroundSaveContext];
}
对象执行提取以及异步从Web服务导入数据这一事实有关。我应该改变它,但我认为这不是唯一的问题。
编辑:这是parentContext
CoreDataHelper
答案 0 :(得分:1)
您的猜测很可能是正确的。通过使用一个用于UI表示的上下文和一个用于后台提取的上下文,您不会遵循自己的模式。
因此,您的第一个行动方案是使用适当的背景上下文进行导入,并使用子上下文进行显示。
尽管如此,我认为将父上下文作为主UI上下文并使用子上下文在后台执行操作更合乎逻辑。然后,子上下文的“保存”会将更改推送到UI。
另外,请务必通过NSManagedObjectContextDidSaveNotification
订阅NSNotificationCenter
并正确合并更改,然后更新用户界面来处理更改。
答案 1 :(得分:0)
经过大量的调试和耐心,我设法找出问题所在。它与并发没有任何关系,在我的谓词中是一个愚蠢的错误。我使用以下代码行:
[fetch setPredicate:[NSPredicate predicateWithFormat:@"shopID==%@", shopID]];
我错误地将shopID用作NSString
,而在我的核心数据模型中,NSManagedObject
它是NSNumber
。我重新考虑改变了商店ID,将其存储为NSString
,现在它完全正常。但是,我仍然无法解释为什么它有时会工作,有时候不会......