2012-03-20 3 views
1

식사와 음식과의 관계가 많습니다 (예 : 식사 < < ------ >> 음식). 음식은 추상적 인 수업이며, 과일이나 야채 일 수 있습니다. 주어진 식사의 모든 음식을 표시하는 RootViewController가 있습니다. 한 클래스에서는 야채를 추가하고 다른 하나는 과일을 추가합니다.핵심 데이터 삽입 오류

식사에 추가하기 시작하면 다음과 같은 오류가 발생합니다. 나는 무슨 일이 일어나고 있는지 그리고 어떻게 일어나고 있는지 잘 모르겠습니다.

Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-1912.3/UITableView.m:1046 

CoreData: error: Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (2) must be equal to the number of rows contained in that section before the update (2), plus or minus the number of rows inserted or deleted from that section (1 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out). with userInfo (null) 
2012-03-19 22:52:06.652 iGlucoTouch[682:11903] Meal Name: Meal #1 atIndex: 0 

RootViewController.h

@interface RootViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, NSFetchedResultsControllerDelegate> 
{    
    NSFetchedResultsController *_fetchedResultsController; 
    NSManagedObjectContext *_context;  

    UITableView *_tableView; 
} 

@property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController; 
@property (nonatomic, retain) NSManagedObjectContext *context; 
@property (nonatomic, retain) UITableView *tableView; 

@end 

RootViewController.m

@implementation RootViewController 

@synthesize fetchedResultsController = _fetchedResultsController; 
@synthesize context = _context; 
@synthesize tableView = _tableView; 


- (void)viewDidAppear:(BOOL)animated 
{ 
    self.tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, 320, 400) style:UITableViewStyleGrouped]; 

    self.tableView.dataSource = self; 
    self.tableView.delegate = self; 
    self.tableView.rowHeight = 60.0; 

    [self.view addSubview:self.tableView]; 
    [self.tableView release]; 

    NSError *error; 
    if (![self.fetchedResultsController performFetch:&error]) { 
     NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
     exit(-1); 
    } 
} 

- (void)tableView:(UITableView *)tableView 
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle 
forRowAtIndexPath:(NSIndexPath *)indexPath 
{  
    self.context = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; 

    Food *food = [_fetchedResultsController objectAtIndexPath:indexPath]; 

    if (editingStyle == UITableViewCellEditingStyleDelete) { 

     [self.meal removeFoodsObject:food]; 

     NSError *error; 
     if (![self.context save:&error]) { 
      NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
      exit(-1); 
     } 
    } 
} 


- (void)tableView:(UITableView *)tableView 
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle 
forRowAtIndexPath:(NSIndexPath *)indexPath 
{  
    self.context = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; 

    Food *food = [_fetchedResultsController objectAtIndexPath:indexPath]; 

    if (editingStyle == UITableViewCellEditingStyleDelete) { 

     [self.meal removeFoodsObject:food]; 

     NSError *error; 
     if (![self.context save:&error]) { 
      NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
      exit(-1); 
     } 
    } 
} 

- (NSFetchedResultsController *)fetchedResultsController 
{  
    self.context = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; 

    if (_fetchedResultsController != nil) { 
     return _fetchedResultsController; 
    } 

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Food" inManagedObjectContext:self.context]; 
    [fetchRequest setEntity:entity]; 

    NSPredicate *foodPredicate = [NSPredicate predicateWithFormat:@"ANY meals == %@", self.meal]; 
    [fetchRequest setPredicate:foodPredicate]; 

    NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES]; 
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];  

    [fetchRequest setFetchBatchSize:20]; 

    NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.context sectionNameKeyPath:nil cacheName:nil]; 

    self.fetchedResultsController = theFetchedResultsController; 
    _fetchedResultsController.delegate = self; 

    [sort release]; 
    [fetchRequest release]; 
    [theFetchedResultsController release]; 

    return _fetchedResultsController; 
} 

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller 
{ 
    [self.tableView beginUpdates]; 
} 

- (void)controller:(NSFetchedResultsController *)controller 
    didChangeObject:(id)anObject 
     atIndexPath:(NSIndexPath *)indexPath 
    forChangeType:(NSFetchedResultsChangeType)type 
     newIndexPath:(NSIndexPath *)newIndexPath 
{   
    switch(type) { 

     case NSFetchedResultsChangeInsert: 
      [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 

     case NSFetchedResultsChangeDelete: 
      [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 

     case NSFetchedResultsChangeUpdate: 
      [self configureCell:[self.tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath]; 
      break; 

     case NSFetchedResultsChangeMove: 
      [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 
    } 
} 

- (void)controller:(NSFetchedResultsController *)controller 
    didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo 
      atIndex:(NSUInteger)sectionIndex 
    forChangeType:(NSFetchedResultsChangeType)type 
{  
    switch(type) { 

     case NSFetchedResultsChangeInsert: 
      [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 

     case NSFetchedResultsChangeDelete: 
      [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 
    } 
} 

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller 
{ 
    [self.tableView endUpdates]; 
} 

나는 다른 클래스에서이 같은 과일이나 야채를 추가

self.context = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; 

Fruit *fruit = [_fetchedResultsController objectAtIndexPath:indexPath]; 

[self.meal addFoodsObject:fruit]; 

NSError *error; 
if (![self.context save:&error]) { 
    NSLog(@"Error: %@", [error localizedDescription]); 
} 
+1

용액은 [이 질문]에서와 유사 할 수있다 (http://stackoverflow.com/questions/2442865/nsfetchedresultscontroller-is-driving-me-crazy). 나는 이전에'UITableView'의 수동 (사용자 중심) 재 배열을 다룰 때 이전에이 오류를 가로 질렀습니다. NSFetchedResultsController 델리게이트 메소드는 모델 중심의 변경과 사용자 중심의 변경을 구별해야했습니다. 그 주제에 관한 [Apple] (https://developer.apple.com/library/ios/#documentation/CoreData/Reference/NSFetchedResultsControllerDelegate_Protocol/Reference/Reference.html) 문서. – FluffulousChimp

+0

고마워, 내가 그 오류를 알아 냈어. – Vikings

답변

1

분명히 fetchedResultsController 및 컨텍스트를 nil로 설정하지 않았습니다. 나는 dealloc에 ​​있었지만 응용 프로그램 델리게이트에서 선언 된 탭 막대의보기 중 하나 였기 때문에 호출되지 않았습니다. 그래서 아래 코드를 추가했습니다. 어쩌면 문맥을 공유하기 때문일 수도 있습니다.

- (void)viewDidDisappear:(BOOL)animated 
{ 
    self.fetchedResultsController = nil; 
    self.context = nil; 
} 
0

예 - 같은 소리 당신은 새로운 전자를 추가하지 않았다. NSFetchResultsController가 지원하는 NSArray에 ntry하십시오. 당신이 [self.meal addFoodsObject:fruit]을 마우스 오른쪽 단추로 후도

[self.tableView insertRowsAtIndexPaths: [NSArray arrayWithObject:newIndexPath] 
            withRowAnimation: UITableViewRowAnimationRight]; 

처럼 자신을 뭔가를 호출 할 수 있어야합니다. Jeff LaMarche의 링크는 훌륭한 설명입니다.

+0

링크가 보이지 않습니다 – Vikings

+0

@ alan-duncan의 링크를 참조하고 있습니다 : http://stackoverflow.com/questions/2442865/nsfetchedresultscontroller-is-driving-me-crazy http로 내부에 Jeff 링크가 있습니다. : //iphonedevelopment.blogspot.ca/2009/11/i-know-youre-tired-of-hearing-about.html –

+0

감사합니다. 오류를 발견했습니다. – Vikings