核心数据拉动变化

时间:2014-07-10 12:52:19

标签: ios objective-c core-data nsmanagedobjectcontext

好的,问题在于:我使用managedObjectContext层次结构。我有一个单managedObjectContext的根,所以我可以共享相同的上下文,同时我可以有子上下文来分隔保存。

_managedObjectContext = [[NSManagedObjectContext alloc]initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];

_managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;

这就是我创建孩子managedObjectContext的方式,我为每个viewController创建一个<{1}}

NSManagedObjectContext* childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
childContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;
childContext.parentContext = _managedObjectContext;

对于那些认为仅仅保存孩子managedObjectContext就足够了的人来说,保存只有一个祖先,你必须这样做,直到父亲为nil。我只有父母和孩子,所以这是我保存数据到存储的代码

- (void)saveChildContext:(NSManagedObjectContext*)childContext
{
    [childContext performBlockAndWait:^{
        NSError* error;
        [childContext save:&error];

        [_managedObjectContext performBlock:^{
            NSError* parentError;
           [_managedObjectContext save:&parentError];
        }];
    }];
}  

我有一个viewController来获取tableView的数据。

arrObjects = [dbClient getEntitiesOfType:@"Object" predicate:@"%K == nil || %K.length < 1" predicateArray:[NSArray arrayWithObjects:@"someRelationship.property", @"someRelationship.otherProperty", nil] childContext:childContext];

这就落后了:

- (NSArray*)getEntitiesOfType:(NSString *)entityType predicate:(NSString*)predicateString predicateArray:(NSArray*)predicateArray childContext(NSManagedObjectContext*)context
{
    NSManagedObjectContext* managedObjectContext;

    if (context != nil)
        managedObjectContext = context;
    else
        managedObjectContext = self.managedObjectContext;

    if (managedObjectContext != nil)
    {
        NSEntityDescription* entityDescription = [NSEntityDescription entityForName:entityType inManagedObjectContext:managedObjectContext];

        NSPredicate* predicate = [NSPredicate predicateWithFormat:predicateString argumentArray:predicateArray];

        NSFetchRequest* request = [[NSFetchRequest alloc] init];
        request.entity = entityDescription;
        request.predicate = predicate;

        NSError* error = [[NSError alloc] init];
        return [managedObjectContext executeFetchRequest:request error:&error];
    }
    else
        return nil;
}

在详细了解其中一个获取结果时,我会进行更改,保存上下文,将更改传播到父级,然后再存储。我传递了对象,并且我使用了对象的managedObjectContext。保存数据到商店后,我弹出我的viewController,一切都很好。

如果我选择在另一个viewController上对该对象执行某些操作,我会保存上下文,因为我做了一些更改,传递objectId,我用另一个managedObjectContext获取该对象,但是拥有相同的父级,进行更改并将其保存到父级,然后存储。一切都很好地存储。哦,我在这里使用NSNotification,因为viewControllers不了解对方的存在。

[self.navigationController popViewControllerAnimated:NO];
    NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys:currentTrip.objectID, @"ObjectId", nil];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"tripRecording" object:nil userInfo:userInfo];

问题是当我到达viewControllertableViewController)时,我在viewWillAppear上获取数据,但我没有得到更改。另一方面,如果我在同一视图上按段,获取另一个数据,然后返回到第一个段,按下它并再次获取第一组数据,我得到正确的答案。这意味着无论我使用哪种上下文,数据都能正确存储。

我的问题是:

  1. 除非我更改managedObjectContext然后再次获取第一个请求,fetchRequest如何才能看到更改?

  2. reset上的managedObjectContext是获取正确数据的唯一途径吗?

  3. 感谢。

1 个答案:

答案 0 :(得分:1)

以下是我使用两个不同NSManagedObjectContext

的设置

创建我的主人NSManagedObjectContext,我从不直接解决这个问题:

- (NSManagedObjectContext *)masterManagedObjectContext {
    if (_masterManagedObjectContext != nil) {
        return _masterManagedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        _masterManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
        [_masterManagedObjectContext performBlockAndWait:^{
            [_masterManagedObjectContext setPersistentStoreCoordinator:coordinator];
        }];

    }
    return _masterManagedObjectContext;
}

动态创建新的NSManagedObjectContext

- (NSManagedObjectContext *)newManagedObjectContext {

    NSManagedObjectContext *newContext = nil;

    NSManagedObjectContext *masterContext = [self masterManagedObjectContext];

    if (masterContext != nil) {

        newContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];

        [newContext performBlockAndWait:^{
            [newContext setParentContext:masterContext];

            NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
            [notificationCenter addObserver:self
                                   selector:@selector(backgroundDidSaveNotification:)
                                       name:NSManagedObjectContextDidSaveNotification
                                     object:newContext];
        }];
    }

    return newContext;
}

侦听新NSManagedObjectContext保存的方法,以便它可以合并为master:

- (void)backgroundDidSaveNotification:(NSNotification*)notificaton {
    [self.masterManagedObjectContext mergeChangesFromContextDidSaveNotification:notificaton];
    [self saveMasterContext];
}

为了清楚起见,我saveMasterContext

- (void)saveMasterContext {
    [self.masterManagedObjectContext performBlockAndWait:^{
        NSError *error = nil;
        BOOL saved = [self.masterManagedObjectContext save:&error];
        if (!saved) {
            // do some real error handling
            NSLog(@"Could not save master context due to %@", error);
        }
    }];
}