本文介绍了核心数据子上下文无法更新主上下文的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

再往下走兔子洞.我已经成功地为我的孩子节省了交通费用:核心数据父/子上下文保存失败

Further down the rabbit hole I go. I've got my child moc saving successfully now:Core Data Parent/Child context save fail

我的下一个障碍是我的Main上下文无法使用子结果更新.基本上,我具有200个条目的表视图现在为空白.

My next hurdle is that my Main context is failing to update with the child results. Basically my tableview that had 200 entries is now blank.

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

Here is my setup: (contains all of the code from previous post)

在我的应用程序委托中,我使用NSMainQueueConcurrencyType设置了主要的托管对象上下文:

In my app delegate I setup the main managedobjectcontext with the NSMainQueueConcurrencyType:

- (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并执行以下工作:

When my data call returns the json I setup the child moc and do the work like this:

- (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方法:

The saveMOC method:

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

好吧,这一直保存到我重新启用帐户"实体和联系人"实体之间的关系为止.

Ok, this was saving until I re-enabled the relationship between a "Account" entity and the "Contact" entity.

客户实体与目的地为联系人"的关系为联系人",反之为客户".删除规则为"Nullify",类型为"To many".

The Account entity has a relationship "contacts" with a destination of "Contact" and the inverse is "accounts". The delete rule is "Nullify" and the type is "To many".

Contact实体与目标"Account"的关系为"accounts",且反向设置为"contacts".删除规则为"Nullify",类型为"To many".

The Contact entity has a relationship "accounts" with a destination of "Account" with inverse set to "contacts". The delete rule is "Nullify" and the type is "To many".

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

The moc error as a result of this relationship is:

Error Domain = NSCocoaErrorDomain代码= 1550联系人无效." UserInfo = {悬空引用无效对象.= null,NSValidationErrorValue =受管对象上的联系人"

Error Domain=NSCocoaErrorDomain Code=1550 "contacts is not valid." UserInfo={Dangling reference to an invalid object.=null, NSValidationErrorValue=Relationship 'contacts' on managed object

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

I think this error is the source of the issue, but for context the following is the NSFetchedResultsController used in the view controller that displays the tableview of contacts:

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

该表在此处生成单元格:

The table generates the cells here:

- (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只是一个上下文时,它会很好地填充.因此,问题是如何使子moc数据正确反映在表视图中.

Ok, That is the rough setup. The tableview would populate fine when it was just one context. So, the question is how to get the child moc data reflected properly in the tableview.

让我知道是否可以提供更多详细信息.

Let me know if I can provide any more details.

推荐答案

破解了!在performBlock之前,我需要通过具有objectWithID的Moc建立帐户实体. BCRAccount account2 =(BCRAccount)[moc objectWithID:[self.loggedInAccount objectID]];之后关系就起作用了:[contact addAccountsObject:account2];

cracked it! before the performBlock i needed to establish the account entity via the moc with objectWithID. BCRAccount account2 = (BCRAccount)[moc objectWithID:[self.loggedInAccount objectID]]; after that the relationship worked: [contact addAccountsObject:account2];

这篇关于核心数据子上下文无法更新主上下文的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-26 06:53