更改为NSFetchedResultsController后,UITableView不更新DataSource

时间:2010-07-16 16:31:09

标签: iphone objective-c uitableview nsfetchedresultscontroller nsfetchrequest

我有一个由UITableView填充的NSFetchedResultsController。初始提取工作正常。我可以添加,删除,修改等零问题。但我想在表中添加用户定义的排序。我这样做是通过更改NSFetchedResultsController以使用不同的sortDescriptor集和不同的sectionNameKeyPath来实现的。这是我更改提取的代码:

-(void)changeFetchData {
    fetchedResultsController = nil;

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Object" inManagedObjectContext:managedObjectContext];
    [fetchRequest setEntity:entity];

    NSString *sortKey = @"sortKey";
    NSString *cacheName = @"myNewCache";
    BOOL ascending = YES;

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:ascending];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
    [fetchRequest setSortDescriptors:sortDescriptors];

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

    [aFetchedResultsController release];
    [fetchRequest release];
    [sortDescriptor release];
    [sortDescriptors release];

    NSError *error;
    if (![[self fetchedResultsController] performFetch:&error]) {
        // Update to handle the error appropriately.
        NSLog(@"Fetch failed");
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        exit(-1);  // Fail
    }

    [self.tableView reloadData];
}

当我称这种方法时,效果很好。该表立即重新排序以使用新的部分信息和新的排序参数。但是,如果我向数据添加或删除项目,TableView不会更新其信息,从而导致崩溃。我可以NSLog对fetchedResultsController中对象总数的计数,并看到它增加(和减少)但是如果我NSLog numberOfRowsInSection的返回值来监视那里的变化,该方法被调用,但值不要改变。得到以下崩溃(添加,但删除类似)

无效更新:第2节中的行数无效。更新后的现有部分中包含的行数(3)必须等于更新前该部分中包含的行数(3),或者减去从该部分插入或删除的行数(插入1个,删除0个)。 with userInfo(null)

如果我重新启动应用程序,我会看到添加的项目,或者看不到已删除的项目,因此我正在修改数据源。

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

旧控制器可能仍然存在。如果是这样,它可能仍然将tableview控制器作为其委托调用,并使用它自己的数据激活表更新。

我建议在numberOfRowsInSection中记录获取的结果控制器对象,以确认它是否使用新控制器。在分配新控制器之前,应将旧控制器的委托设置为nil。

答案 1 :(得分:0)

有一次,添加:

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

解决了一个类似的问题,当行数发生变化但数据保持不同且不是最新时会出现这个问题。