Reputation: 29524
Whenever I have data in my UITableView
and I start deleting, it works fine. However, when I get to the last object in the table, and delete it, it crashes.
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 (1) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted).'
Here's how I'm doing the editing stuff:
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
if ([myData count] >= 1) {
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[myData removeObjectAtIndex:[indexPath row]];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *somepath = [documentsDirectory stringByAppendingPathComponent:@"something.plist"];
[myData writeToFile:somepath atomically:YES];
[table reloadData];
if ([myData count] == 0) {
[tableView endUpdates];
[tableView reloadData];
}
else {
[tableView endUpdates];
}
}
}
}
And also this:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
if ([myData count] != 0) {
return [myData count];
}
else {
return 1;
}
}
The reason I'm returning 1 is because I'm making a cell that says "No data saved" in cellForRowAtIndexPath
. Here's what I mean:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
if ([cityData count] != 0) {
//normal setup removed for clarity
}
else {
cell.textLabel.text = @"No saved data!";
cell.textLabel.font = [UIFont boldSystemFontOfSize:14];
cell.textLabel.textAlignment = UITextAlignmentCenter;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.tag = 1;
return cell;
}
}
So, what am I doing wrong in my editing code to get this error? Thanks!
Upvotes: 15
Views: 19779
Reputation: 3155
The method tableView:numberOfRowsInSection
must always return exact number of rows:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return [myData count];
}
After having deleted last row, you may want to delete the whole section. Simply call deleteSections:withRowAnimation:
within a beginUpdates
and endUpdated
block;
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[myData removeObjectAtIndex:[indexPath row]];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *somepath = [documentsDirectory stringByAppendingPathComponent:@"something.plist"];
[myData writeToFile:somepath atomically:YES];
if ([myData count] == 0) {
// NEW! DELETE SECTION IF NO MORE ROWS!
[tableView deleteSections:[NSIndexSet indexSetWithIndex:[indexPath section]] withRowAnimation:UITableViewRowAnimationFade];
}
[tableView endUpdates];
}
}
Upvotes: 1
Reputation: 11
first remove from myData and then delete from tableview.
-(void)tableView:(UITableView *)tableView commitEditingStyle:
(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
//somehting...
[myData removeObjectAtIndex:[indexPath row]];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
//somehting...
}
}
}
Upvotes: 1
Reputation: 5200
If you delete the last row in your table, the UITableView
code expects there to be 0 rows remaining. It calls your UITableViewDataSource
methods to determine how many are left. Since you have a "No data" cell, it returns 1, not 0. So when you delete the last row in your table, try calling -insertRowsAtIndexPaths:withRowAnimation:
to insert your "No data" row. Also, you should not call -reloadData
anywhere in this method. -endUpdates
will take care of reloading the affected rows. Try this out:
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
if ([myData count] >= 1) {
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[myData removeObjectAtIndex:[indexPath row]];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *somepath = [documentsDirectory stringByAppendingPathComponent:@"something.plist"];
[myData writeToFile:somepath atomically:YES];
if ([myData count] == 0) {
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
[tableView endUpdates];
}
}
}
Upvotes: 29