批量更新后更新托管对象上的托管对象

时间:2014-09-18 05:25:13

标签: ios objective-c core-data ios8

使用iOS 8以来提供的NSBatchUpdateRequest类执行批量更新时,任何现有的托管对象上下文都不知道对持久性存储所做的更改。我的问题是如何更新托管对象上下文以反映持久性存储中的更改。

我正在使用获取的结果控制器,并且我已经尝试通过调用托管对象上下文中的refreshObject:mergeChanges:并重新加载表视图来将每个托管对象转换为错误,但这并不是&#39似乎可以做到这一点。

2 个答案:

答案 0 :(得分:2)

可以将NSBatchUpdateRequest设置为结果类型为NSStatusOnlyResultTypeNSUpdatedObjectIDsResultTypeNSUpdatedObjectsCountResultTypeNSUpdatedObjectIDsResultType是唯一一个返回有关批处理操作影响对象的有意义信息的人。

使用对象ID,您可以通知您的上下文需要刷新这些对象。任何获取结果控制器观察上下文都将看到更改通知并相应地采取行动。

示例:如何解雇所有人。

[context performBlock:^{
    NSError                 *batchError     = nil;
    NSBatchUpdateRequest    *batchRequest   = nil;
    NSBatchUpdateResult     *batchResult    = nil;

    batchRequest = [NSBatchUpdateRequest batchUpdateRequestWithEntityName:@"Employee"];
    [batchRequest setPropertiesToUpdate:@{@"employed" : @NO}];
    [batchRequest setPredicate:nil];
    [batchRequest setAffectedStores:[[context persistentStoreCoordinator] persistentStores] ];
    [batchRequest setResultType:NSUpdatedObjectIDsResultType];
    batchResult = (NSBatchUpdateResult *)[context executeRequest:batchRequest error:&batchError];

    if ([[batchResult result] respondsToSelector:@selector(count)]){
        if ([[batchResult result] count] > 0){
            [context performBlock:^{
                for (NSManagedObjectID *objectID in [batchResult result]){
                    NSError         *faultError = nil;
                    NSManagedObject *object     = [context existingObjectWithID:objectID error:&faultError];
                    // Observers of this context will be notified to refresh this object.
                    // If it was deleted, well.... not so much.
                    [context refreshObject:object mergeChanges:YES];
                }
            }];
        } else {
            // We got back nothing!
        }
    } else {
        // We got back something other than a collection
    }
}];

显然,有很多情况会无法满足您的需求,或者根本无法运作。您可能必须刷新相当多的上下文 - 在一系列上下文中递归执行刷新块确实有效,但是不会发现任何兄弟情况的上下文(这是避免创建兄弟节点的另一个原因)。

答案 1 :(得分:0)

- (NSBatchUpdateResult*)executeBatchUpdateRequest:(NSBatchUpdateRequest*)request
                                          context:(NSManagedObjectContext*)context
                                            error:(NSError**)error{
    NSBatchUpdateResult *bur = (NSBatchUpdateResult *)[context executeRequest:request error:error];
    if (bur && bur.resultType == NSUpdatedObjectIDsResultType){
        NSArray <NSManagedObjectID*> *arr = bur.result;
        if ([arr isKindOfClass:NSArray.class] && arr.count > 0){
            // can update multiple contexts
            [NSManagedObjectContext mergeChangesFromRemoteContextSave:@{NSUpdatedObjectsKey:arr}
                                                         intoContexts:@[context]];
    }
    return bur;
}

}