繁体   English   中英

NSFetchRequest关于didEnterRegion并发问题

[英]NSFetchRequest on didEnterRegion concurrency issue

我是Core Data的新手,我研究了许多与Cored Data相关的问题,但是我无法真正完全掌握Core Data和并发的整个概念。 似乎有一种方法可以做到,但是近年来它发生了变化,现在很难过滤出哪些信息是最新的,哪些不是最新的。 我正在开发一个小型应用程序,该应用程序从Web服务导入商店数据,将其呈现给用户,并监视用户何时进入特定商店的区域。 我正在使用两个NSManagedObjectContext ,它们是CoreDataHelper类的一部分。 这是作为单例实现的CoreDataHelperinit

- (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

- (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];
}

但是有时,并非总是如此,即使该请求100%存在,提取请求也找不到具有给定ID的商店。 该问题仅在某些时候发生的事实使我得出结论,这与并发性有关。 另外,我认为这可能与以下事实有关:我在此处使用相同的parentContext对象来执行获取操作,并且还异步地从Web服务中导入数据。 我可能应该更改它,但是我认为这不是唯一的问题。

编辑:这是CoreDataHelper保存机制

- (void)saveContext
{

    if ([_context hasChanges]) {
        NSError* error = nil;
        if ([_context save:&error]) {
            NSLog(@"_context SAVED changes to persistent store");
        }
        else {
            NSLog(@"Failed to save _context: %@", error);
        }
    }
    else {
        NSLog(@"SKIPPED _context save, there are no changes!");
    }
}
- (void)backgroundSaveContext {

    // First, save the child context in the foreground (fast, all in memory)
    [self saveContext];

    // Then, save the parent context.
    [_parentContext performBlock:^{
        if ([_parentContext hasChanges]) {
            NSError *error = nil;
            if ([_parentContext save:&error]) {
                NSLog(@"_parentContext SAVED changes to persistent store");
            }
            else {
                NSLog(@"_parentContext FAILED to save: %@", error);
            }
        }
        else {
            NSLog(@"_parentContext SKIPPED saving as there are no changes");
        }
    }];
}

您的猜测很可能是正确的。 您不会通过将一种上下文用于UI表示而将一种上下文用于后台提取来遵循自己的模式。

因此,您的第一个操作步骤是使用适当的背景上下文进行导入,并使用子上下文进行显示。

不过,我认为将父上下文作为主要的UI上下文并使用子上下文在后台进行操作会更加合乎逻辑。 然后,子上下文的“保存”会将更改推送到UI。

另外,请确保通过NSNotificationCenter订阅NSManagedObjectContextDidSaveNotification并正确合并更改,然后更新用户界面来处理更改。

经过大量的调试和耐心,我设法查明了问题所在。 它与并发无关,在我的谓语中是一个愚蠢的错误。 我正在使用以下代码行:
[fetch setPredicate:[NSPredicate predicateWithFormat:@"shopID==%@", shopID]];

我错误地将shopID用作NSString而在我的核心数据模型和NSManagedObject它是一个NSNumber 我重新考虑了将shopID更改为存储为NSString ,现在它可以正常工作。 但是我仍然无法解释为什么它有时会工作,有时却无法工作...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM