核心数据子上下文无法更新主上下文

时间:2015-11-09 23:22:41

标签: objective-c multithreading uitableview core-data

在兔子洞的下方,我走了。我现在已经成功保存了我的孩子moc: Core Data Parent/Child context save fail

我的下一个障碍是我的主要上下文无法使用子结果进行更新。基本上我有200个条目的tableview现在是空白的。

以下是我的设置:(包含上一篇文章中的所有代码)

在我的app委托中,我使用NSMainQueueConcurrencyType设置主要的managedobjectcontext:

- (NSManagedObjectContext *)managedObjectContext
{
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {

        _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];//[[NSManagedObjectContext alloc] init];
        //_managedObjectContext = [[NSManagedObjectContext alloc] init];
        [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return _managedObjectContext;
}

当我的数据调用返回json时,我设置了子moc并按照以下方式进行工作:

- (void)APIManager:(APIManager *)manager didGetContactsWithInfo:(NSDictionary *)info
{

    NSManagedObjectContext *mainMOC = self.managedObjectContext;
    NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];

    [moc setParentContext:mainMOC];
    [moc setUndoManager:nil];

BCRAccount *account2 = (BCRAccount*)[moc objectWithID:[self.loggedInAccount objectID]];

     [moc performBlock:^{
        //do all work on child moc
        //within block there is a core data relationship reference:


[contact addAccountsObject:account2];

            [self saveMOC:moc completion:^(NSError *error) {
                // Completion handler is called from main-thread, after save has finished
                if (error) {
                    // Handle error
                    NSLog(@"save error %@", error);
                } else {
                    NSLog(@"save success");

                }
            }];

}];

saveMOC方法:

- (void)saveMOC:(NSManagedObjectContext*)moc
     completion:(void(^)(NSError *error))completion {
    [moc performBlock:^{
        NSError *error = nil;
        if ([moc save:&error]) {
            if (moc.parentContext) {
                return [self saveMOC:moc.parentContext completion:completion];
            }
        }
        if (completion) {
            dispatch_async(dispatch_get_main_queue(), ^{
                completion(error);
        }
    }];
}

好的,这是保存,直到我重新启用“帐户”实体和“联系”实体之间的关系。

帐户实体与目的地为“联系人”的关系为“联系人”,反之为“帐户”。删除规则为“Nullify”,类型为“To many”。

联系人实体的关系为“帐户”,目的地为“帐户”,反向设置为“联系人”。删除规则为“Nullify”,类型为“To many”。

这种关系导致的moc错误是:

错误域= NSCocoaErrorDomain代码= 1550“联系人无效。” UserInfo = {悬挂对无效对象的引用。= null,NSValidationErrorValue =托管对象上的关系'联系人'

我认为此错误是问题的根源,但对于上下文,以下是视图控制器中使用的NSFetchedResultsController,它显示联系人的表视图:

- (NSFetchedResultsController *)fetchedResultsController
{
    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:[BCRContact entityName] inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    // Set the batch size to a suitable number.
    [fetchRequest setFetchBatchSize:20];

    // Edit the sort key as appropriate.

   NSArray *sortDescriptors =
    @[[NSSortDescriptor sortDescriptorWithKey:@"isNewContact" ascending:NO],
      [NSSortDescriptor sortDescriptorWithKey:@"status" ascending:YES],
      [NSSortDescriptor sortDescriptorWithKey:@"fullName" ascending:YES],
      [NSSortDescriptor sortDescriptorWithKey:@"company" ascending:YES]];

    [fetchRequest setSortDescriptors:sortDescriptors];

    fetchRequest.predicate = [self predicateWithSearchString:nil];

    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;

    NSError *error = nil;
    if (![self.fetchedResultsController performFetch:&error]) {
        // Replace this implementation with code to handle the error appropriately.
        // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
        //NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return _fetchedResultsController;
}

该表在此处生成单元格:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

    static NSString *CellIdentifier = @"Cell";

    ContactListCell *cell = (ContactListCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[ContactListCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
        cell.selectionStyle = UITableViewCellSelectionStyleGray;
    }

    [self configureCell:cell atIndexPath:indexPath];
    return cell;
 }

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
    BCRContact *contact = [self.fetchedResultsController objectAtIndexPath:indexPath];
    //update cell
 }

好的,这是粗略的设置。当tableview只是一个上下文时,tableview会很好。所以,问题是如何在tableview中正确反映孩子的moc数据。

如果我能提供更多细节,请告诉我。

1 个答案:

答案 0 :(得分:1)

破解了!在performBlock之前我需要通过带有objectWithID的moc建立帐户实体。 BCRAccount account2 =(BCRAccount)[moc objectWithID:[self.loggedInAccount objectID]];之后关系工作:[联系addAccountsObject:account2];