更改为 NSFetchedResultsController 后 UITableView 未更新数据源
我有一个由 NSFetchedResultsController
填充的 UITableView
。初始获取工作正常。我可以添加、删除、修改等,零问题。但我想向表中添加用户定义的排序。我通过将 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)
如果我重新启动应用程序,我会看到添加的项目,或者看不到删除的项目,因此我正在正确修改数据源。
有什么想法吗?
I have an UITableView
populated by a NSFetchedResultsController
. The initial fetch works fine. I can add, remove, modify, etc with zero problems.. But I want to add user-defined sorting to the table. I am doing this by changing the NSFetchedResultsController
to use a different sortDescriptor
set, and a different sectionNameKeyPath
. Here is the code where I change the fetch:
-(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];
}
When I call this method, it works great. The table immediately re-orders itself to use the new section info, and the new sorting parameters. But if I add or remove items to the data, the TableView doesn't update its info, causing a crash. I can NSLog the count of the total number of objects in the fetchedResultsController, and see it increase (and decrease) but if I NSLog the return values for numberOfRowsInSection
to monitor a change there, the method gets called, but the values don't change. The get the following crash (for addition, but the deletion one is similar)
Invalid update: invalid number of rows in section 2. The number of rows contained in an existing section after the update (3) must be equal to the number of rows contained in that section before the update (3), plus or minus the number of rows inserted or deleted from that section (1 inserted, 0 deleted). with userInfo (null)
If I restart the app, I see the added item, or do not see the deleted item, so I am modifying the datasource correctly.
Any ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
旧控制器可能还活着。如果是这样,它可能仍然会调用表视图控制器作为其委托,并使用它自己的数据激活表更新。
我建议在
numberOfRowsInSection
中记录获取的结果控制器对象,以确认它使用新的控制器。在分配新控制器之前,您应该将旧控制器的委托设置为 nil。It's possible that the old controller is still alive. If so, it might still be calling the tableview controller as its delegate and activating the table update using it's own data.
I would suggest logging the fetched results controller object in
numberOfRowsInSection
to confirm that it using the new controller. You should set the old controller's delegate to nil before assigning the new one.有一次,添加:
解决了当行数发生变化但所保存的数据仍然不同且不是最新时出现的类似问题。
On one occasion, adding:
Solved a similar issue which arises when number of rows changes but data held is still different and not up-to-date.