删除行:错误“无效更新:第 0 节中的行数无效”
Posted
技术标签:
【中文标题】删除行:错误“无效更新:第 0 节中的行数无效”【英文标题】:Deleting row: error 'Invalid update: invalid number of rows in section 0' 【发布时间】:2013-10-30 09:34:56 【问题描述】:2013 年 11 月 24 日:我做了更多调试,发现 removeProject 工作正常。 (我在删除前后打印了所有项目)只有当它返回 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 时,计数为 0 而不是(total - 1)。
============
我现在被这个错误困住了一段时间。为了更好地理解 Core Data,我创建了这个测试项目,您可以在其中输入客户和他的项目。这些项目与客户有关。 对于项目,我复制了 Clients 的 ViewController 并进行了一些小改动。 我可以输入几个客户,然后删除它们。当我想删除相关项目时,问题就开始了。如果有一个客户只有一个项目,我可以删除它而不会出现任何错误。如果客户有两个或更多项目,我无法从该客户中删除任何项目。 删除会给我这个错误:
2013-10-30 10:00:23.145 [6160:70b] *** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-2903.2/UITableView.m:1330
2013-10-30 10:00:23.147 [6160:70b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (0) 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 (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
*** First throw call stack:
(
.....
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Program ended with exit code: 0
在这个网站上阅读了很多答案后,我的猜测是我需要更改我的代码 numberOfRowsInSection 方法,但我看不到那里要改变什么。
我的代码:
我创建了一个数据存储:
DataStore.m
#import "BITDataStore.h"
#import "Client.h"
#import "Project.h"
@implementation DataStore
+ (BITDataStore *)sharedStore
static BITDataStore *sharedStore = nil;
if (!sharedStore)
sharedStore = [[super allocWithZone:nil]init];
return sharedStore;
-(void)removeClient:(Client *)client
// remove from NSManagedObjectContext
[context deleteObject:client];
// remove from allClients array
[allClients removeObjectIdenticalTo:client];
NSLog(@"remove client");
-(void)removeProject:(Project *)project
// remove from NSManagedObjectContext
[context deleteObject:project];
// remove from allProjects array
[allProjects removeObjectIdenticalTo:project];
// remove from relatedProjects array
[relatedProjects removeObjectIdenticalTo:project];
NSLog(@"remove project %@", [project project]);
-(NSArray *)relatedProjects:(Client *)client;
NSFetchRequest *request = [[NSFetchRequest alloc]init];
NSEntityDescription *e = [[model entitiesByName] objectForKey:@"Project"];
[request setEntity:e];
// Check if client is related to Project
[request setPredicate: [NSPredicate predicateWithFormat:@"clients == %@", client.objectID]];
NSSortDescriptor *sd = [NSSortDescriptor sortDescriptorWithKey:@"project"
ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObject:sd]];
NSError *error;
NSArray *result = [context executeFetchRequest:request error:&error];
if (!result)
[NSException raise:@"Fetch failed"
format:@"Reason: %@", [error localizedDescription]];
relatedProjects = [[NSMutableArray alloc] initWithArray:result];
return relatedProjects;
@end
ProjectDataViewController.m
@synthesize client, project;
-(void)viewWillAppear:(BOOL)animated
[super viewWillAppear:animated];
[[self tableView] reloadData];
#pragma mark - Table view data source
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
return [[[BITDataStore sharedStore]relatedProjects:client]count];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
if (cell == nil)
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
Project *p = [[[BITDataStore sharedStore]relatedProjects:client]
objectAtIndex:[indexPath row]];
[[cell textLabel] setText:[p project]];
return cell;
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
if (editingStyle == UITableViewCellEditingStyleDelete)
BITDataStore *ds = [BITDataStore sharedStore];
NSArray *selectedProjects = [ds relatedProjects:client];
Project *pr = [selectedProjects objectAtIndex:[indexPath row]];
NSLog(@"Deleting project %@", [pr project]);
[ds removeProject:pr];
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
// Finally, reload data in view
[[self tableView] reloadData];
NSLog(@"Reload data");
else if (editingStyle == UITableViewCellEditingStyleInsert)
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
@end
希望这是足够的信息,如果没有,请告诉我。
【问题讨论】:
代码转储太多。请减少。 谢谢,我已经减少代码了。 您的 deleteObject 可能是问题所在。例如,如果你从 NSMutableArray 中删除,delete (removeObjectAtIndex 反过来) 只会插入 nil。它不会删除整个对象。看看它。其他一切似乎都很好。 嗨,你的意思是这个代码“[context deleteObject:client];”吗?这是一个 NSManagedObjectContext,我不知道如何以不同的方式删除它,是吗? 我们的 removeProject 是否按预期工作?此外,之后无需重新加载表格视图。 【参考方案1】:将我的删除规则从级联更改为无效并且它有效。
【讨论】:
【参考方案2】:虽然需要阅读更多代码才能确定,但从您的描述看来,问题在于删除元素时表格视图更新不正确。
为了更好地理解Core Data,我创建了这个测试项目
我的建议是从标准 Apple 模板之一开始。特别是,他们展示了如何使用NSFetchedResultsController
来避免此类问题。
您也可以查看博文Core Data Tutorial for ios: How To Use NSFetchedResultsController。
【讨论】:
以上是关于删除行:错误“无效更新:第 0 节中的行数无效”的主要内容,如果未能解决你的问题,请参考以下文章
NSInternalInconsistencyException 原因:'无效更新:第 0 节中的行数无效'
tableView 编辑委托方法不起作用(无效更新:第 0 节中的行数无效)
NSInternalInconsistencyException(无效更新:第 0 节中的行数无效)
iOS 8:从 NSFetchedResultsController 的委托中捕获异常,无效更新:第 0 节中的行数无效
应用程序崩溃:由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“无效更新:第 0 节中的行数无效