编辑包含 NSFetchedResults 的 TableView
Edit TableView containing NSFetchedResults
从我的核心数据中删除使用 NSFetchedResultsController 获取并显示在 TableView 中的对象时,它不会更新 table。它很好地删除了对象,但是该行仍然存在,直到我交换视图和 return。我注意到这个问题从 iOS8 开始才开始发生,但可能是错误的。下面是我的代码:
#pragma mark - Fetched Results Controller Delegate
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSManagedObjectContext * context = [self managedObjectContext];
entity * rowToDelete = [self.fetchedResultsController objectAtIndexPath:indexPath];
[context deleteObject:rowToDelete];
//check that the row has deleted data
NSLog(@"Shhiiiiiiiiii...... You done did delete a row...");
NSError * error = nil;
if (![context save:&error]){
NSLog(@"Error: %@", error);
}
//causes a crash
//[self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationRight];
//DOES NOT UPDATE THE TABLE
[self.tableView reloadData];
}
}
我像这样使用所有普通代表:
- (void) controllerWillChangeContent:(NSFetchedResultsController *)controller{
[self.tableView beginUpdates];
}
- (void) controllerDidChangeContent:(NSFetchedResultsController *)controller{
[self.tableView endUpdates];
}
- (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:UITableViewRowAnimationRight];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
break;
case NSFetchedResultsChangeUpdate:{
entity * details = [self.fetchedResultsController objectAtIndexPath:indexPath];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
cell.textLabel.text = details.detailString;
}
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:UITableViewRowAnimationRight];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationRight];
break;
case NSFetchedResultsChangeMove:
NSLog(@"A table item was moved");
break;
case NSFetchedResultsChangeUpdate:
NSLog(@"A table item was updated");
break;
}
}
我在 Stack 上搜索并找到了通用响应 "You need to use [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationRight];
"。这是行不通的。
在此先感谢您的帮助。如果我没有立即回复,那是因为我正在休息或睡着了 ;-)
NSFetchedResultsController 应该能够为您传达所有更改。
- 检查是否正在调用更新函数(即缩小可能失败的位置)
- 检查 NSFetchedResultsController 实例是否设置了委托
- 检查您是否在相同或连接的上下文中工作(即检查通知是否有传播的机会)
- 我不确定您是否可以忽略重新排序(可能取决于您的方法)但假设 [对象 A,第 1 行] 与 [对象 B,第 2 行] 交换,然后对象 B 被删除, 系统如何知道要删除哪 table 行(除非你对信息做一些额外的事情)
从 table 中手动删除一行将导致崩溃,因为数据源将与 table 不一致——因此,会导致各种混乱。结果的委托方法可以使实际结果与 table.
中显示的结果同步
我从一个工作演示中删除了以下内容(尽管在途中修改了一堆东西)。它工作并接收更改,并更新 table。 google 之外还有几篇博文也有帮助。
- (void)viewDidLoad {
[super viewDidLoad];
_fetchedResultsController = /* my fetched results controller... */;
_fetchedResultsController.delegate = self;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
NSInteger count = [[_fetchedResultsController sections] count];
return count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
id sectionInfo = [[_fetchedResultsController sections] objectAtIndex:section];
NSInteger count = [sectionInfo numberOfObjects];
return count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
return [self configureCell:nil atIndexPath:indexPath];
}
- (UITableViewCell *)configureCell:(UITableViewCell*)cell atIndexPath:(NSIndexPath*)indexPath {
id obj = [self.fetchedResultsController objectAtIndexPath:indexPath];
if(!cell) {
cell = [self.tableView dequeueReusableCellWithIdentifier:@"MyTableViewCell" forIndexPath:indexPath];
}
cell.textLabel.text = obj.someProperty;
return cell;
}
#pragma mark NSFetechResults delegate
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id )sectionInfo
atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationAutomatic];
break;
default:
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath {
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath]
atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationAutomatic];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self.tableView endUpdates];
}
我傻傻的放了
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self.tableView endUpdates];
}
在动作更新之前开始。新手错误。希望它能帮助其他同样陷入困境的人。
从我的核心数据中删除使用 NSFetchedResultsController 获取并显示在 TableView 中的对象时,它不会更新 table。它很好地删除了对象,但是该行仍然存在,直到我交换视图和 return。我注意到这个问题从 iOS8 开始才开始发生,但可能是错误的。下面是我的代码:
#pragma mark - Fetched Results Controller Delegate
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSManagedObjectContext * context = [self managedObjectContext];
entity * rowToDelete = [self.fetchedResultsController objectAtIndexPath:indexPath];
[context deleteObject:rowToDelete];
//check that the row has deleted data
NSLog(@"Shhiiiiiiiiii...... You done did delete a row...");
NSError * error = nil;
if (![context save:&error]){
NSLog(@"Error: %@", error);
}
//causes a crash
//[self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationRight];
//DOES NOT UPDATE THE TABLE
[self.tableView reloadData];
}
}
我像这样使用所有普通代表:
- (void) controllerWillChangeContent:(NSFetchedResultsController *)controller{
[self.tableView beginUpdates];
}
- (void) controllerDidChangeContent:(NSFetchedResultsController *)controller{
[self.tableView endUpdates];
}
- (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:UITableViewRowAnimationRight];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
break;
case NSFetchedResultsChangeUpdate:{
entity * details = [self.fetchedResultsController objectAtIndexPath:indexPath];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
cell.textLabel.text = details.detailString;
}
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:UITableViewRowAnimationRight];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationRight];
break;
case NSFetchedResultsChangeMove:
NSLog(@"A table item was moved");
break;
case NSFetchedResultsChangeUpdate:
NSLog(@"A table item was updated");
break;
}
}
我在 Stack 上搜索并找到了通用响应 "You need to use [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationRight];
"。这是行不通的。
在此先感谢您的帮助。如果我没有立即回复,那是因为我正在休息或睡着了 ;-)
NSFetchedResultsController 应该能够为您传达所有更改。
- 检查是否正在调用更新函数(即缩小可能失败的位置)
- 检查 NSFetchedResultsController 实例是否设置了委托
- 检查您是否在相同或连接的上下文中工作(即检查通知是否有传播的机会)
- 我不确定您是否可以忽略重新排序(可能取决于您的方法)但假设 [对象 A,第 1 行] 与 [对象 B,第 2 行] 交换,然后对象 B 被删除, 系统如何知道要删除哪 table 行(除非你对信息做一些额外的事情)
从 table 中手动删除一行将导致崩溃,因为数据源将与 table 不一致——因此,会导致各种混乱。结果的委托方法可以使实际结果与 table.
中显示的结果同步我从一个工作演示中删除了以下内容(尽管在途中修改了一堆东西)。它工作并接收更改,并更新 table。 google 之外还有几篇博文也有帮助。
- (void)viewDidLoad {
[super viewDidLoad];
_fetchedResultsController = /* my fetched results controller... */;
_fetchedResultsController.delegate = self;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
NSInteger count = [[_fetchedResultsController sections] count];
return count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
id sectionInfo = [[_fetchedResultsController sections] objectAtIndex:section];
NSInteger count = [sectionInfo numberOfObjects];
return count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
return [self configureCell:nil atIndexPath:indexPath];
}
- (UITableViewCell *)configureCell:(UITableViewCell*)cell atIndexPath:(NSIndexPath*)indexPath {
id obj = [self.fetchedResultsController objectAtIndexPath:indexPath];
if(!cell) {
cell = [self.tableView dequeueReusableCellWithIdentifier:@"MyTableViewCell" forIndexPath:indexPath];
}
cell.textLabel.text = obj.someProperty;
return cell;
}
#pragma mark NSFetechResults delegate
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id )sectionInfo
atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationAutomatic];
break;
default:
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath {
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath]
atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationAutomatic];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self.tableView endUpdates];
}
我傻傻的放了
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self.tableView endUpdates];
}
在动作更新之前开始。新手错误。希望它能帮助其他同样陷入困境的人。