2015-11-09 3 views
0

Далее вниз по кроличьей дыре я иду. Теперь у меня есть моя экономия на мокере для детей: Core Data Parent/Child context save failОсновные данные Контекст ребенка не обновляется Основной контекст

Следующим препятствием является то, что мой основной контекст не обновляется с результатами ребенка. В основном моя таблица, в которой было 200 записей, теперь пуста.

Вот мои настройки: (содержит весь код из предыдущего поста)

В моей установке приложения делегат I главный managedobjectcontext с 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 и выполняю следующие действия:

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

Объект Contact имеет отношение «учетные записи» с адресом «Учетная запись» с инверсным значением «контакты». Правило удаления - «Nullify», а тип «To many».

МОЦ ошибка в результате этих отношений:

Ошибка Доменные = NSCocoaErrorDomain Код = 1550 «контакты не действует.» UserInfo = {Неверная ссылка на недопустимый объект. = Null, NSValidationErrorValue = Связь «контакты» на управляемом объекте

Я думаю, что эта ошибка является источником проблемы, но для контекста следующим является NSFetchedResultsController, используемый в контроллере представления который отображает TableView контактов:

- (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 будет заполняться отлично, когда это будет только один контекст. Итак, вопрос заключается в том, как получить детальные данные moc, правильно отраженные в представлении таблицы.

Сообщите мне, если я могу предоставить более подробную информацию.

+0

Только взял быстрый взгляд ... собирался поужинать и пообщаться с женой немного ... Вот несколько вопросов, хотя ... что делает этот метод создания предикатов? Получаете ли вы те же результаты, если просто удалите это? Правильно ли вы выполняете делегат FRC? Может быть, поставить точку останова и/или некоторое ведение журнала в методе 'controllerDidChangeContent:', чтобы убедиться, что FRC видит изменения.Кроме того, вы можете сделать выборку в обработчике завершения из сохранения, чтобы убедиться, что вы видите то, что ожидаете увидеть. –

+0

Tangent: вы должны использовать '[tableView dequeueReusableCellWithIdentifier: atIndexPath:]'. Этот метод * всегда * возвращает ячейку, поэтому следующий оператор if не нужен. Есть и другие преимущества, связанные с проверками времени выполнения. – Avi

+0

После некоторого рытья я обнаружил осязаемую ошибку. Я получаю оборванную ссылочную ошибку, основанную на отношениях между сущностью «Учетная запись» и «Контакт». Я отключил отношения, думая, что это, возможно, не было необходимо, но теперь я думаю, что лучший способ - выяснить, что вызывает эту ошибку. Я обновил сообщение с информацией. –

ответ

1

треснул его! перед выполнением блокировки мне нужно было создать объект учетной записи через moc с objectWithID. BCRAccount account2 = (BCRAccount) [moc objectWithID: [self.loggedInAccount objectID]]; после этого отношения работали: [contact addAccountsObject: account2];

Смежные вопросы