Reputation: 280
I create a table view and everything work's fine. I want always display 1 cell in my table view with title "You should add cell". Then when I add information to my array (tableData) I need to display this information in my custom cell. Then when I delete this cell I need to display my 1 cell with title "You should add cell". But I can't do this(Please explain me why?)
My code:
- (void)viewDidLoad {
[super viewDidLoad];
_tableData = [[NSMutableArray alloc] init];
[self.tableView setDelegate:self];
[self.tableView setDataSource:self];
self.tableData = [NSMutableArray arrayWithArray:[[SOCoreDataManager sharedManager] getAllAims]];
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
if ([self.tableData count] == 0) {
return 1;
}
return [self.tableData count];
}
- (UITableViewCell *)tableView:(UITableView *)table
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString* cellID = @"cellForMyAims";
if ((int)[self.tableData count] == 0) {
static NSString* cellIDw = @"Cell";
UITableViewCell *cellw = [table dequeueReusableCellWithIdentifier:cellIDw];
if (!cellw) {
cellw = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIDw];
}
cellw.backgroundColor = [UIColor orangeColor];
return cellw;
} else {
CellForMyAimsTableViewCell *cell = [table dequeueReusableCellWithIdentifier:cellID];
if (!cell) {
cell = [[CellForMyAimsTableViewCell alloc] initWithFrame:CGRectZero];;
}
return cell;
}
}
And I delete:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
SOGoal *goal = self.tableData [indexPath.row];
[[SOCoreDataManager sharedManager] deleteAim:goal];
self.tableData = [NSMutableArray arrayWithArray:[[SOCoreDataManager sharedManager] getAllAims]];
[self.tableView beginUpdates];
[self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
[self.tableView endUpdates];
}
}
Error:
2015-01-14 15:17:25.019 [5332:190142] *** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-3318.16.14/UITableView.m:1582
2015-01-14 15:17:25.022 [5332:190142] *** 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) 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:
(
0 CoreFoundation 0x00000001050bcf35 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x0000000104d55bb7 objc_exception_throw + 45
2 CoreFoundation 0x00000001050bcd9a +[NSException raise:format:arguments:] + 106
3 Foundation 0x00000001049725df -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 195
4 UIKit 0x000000010337bc2a -[UITableView _endCellAnimationsWithContext:] + 11746
5 nameapp 0x00000001029777cf __69-[ListViewController tableView:commitEditingStyle:forRowAtIndexPath:]_block_invoke + 607
6 nameapp 0x000000010297ea10 __86+[SONetworkingWithLegendaryServer deleteAim:legendaryToken:aimId:onSuccess:onFailure:]_block_invoke + 112
7 nameapp 0x000000010296dad8 __64-[AFHTTPRequestOperation setCompletionBlockWithSuccess:failure:]_block_invoke46 + 40
8 libdispatch.dylib 0x0000000106673ba6 _dispatch_call_block_and_release + 12
9 libdispatch.dylib 0x00000001066917f4 _dispatch_client_callout + 8
10 libdispatch.dylib 0x000000010667a8fb _dispatch_main_queue_callback_4CF + 949
11 CoreFoundation 0x0000000105024fe9 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
12 CoreFoundation 0x0000000104fe7eeb __CFRunLoopRun + 2043
13 CoreFoundation 0x0000000104fe7486 CFRunLoopRunSpecific + 470
14 GraphicsServices 0x00000001070569f0 GSEventRunModal + 161
15 UIKit 0x00000001032a7420 UIApplicationMain + 1282
16 nameapp 0x00000001029c52e3 main + 115
17 libdyld.dylib 0x00000001066c6145 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Upvotes: 1
Views: 247
Reputation: 7416
You're getting the NSInternalInconsistencyException
because your table will always have at least one row but when you swipe-to-delete the last row you're telling it you expect to end up with 0 cells. This obvious mismatch generates the exception.
To fix it, tableView:commitEditingStyle:forRowAtIndexPath:
needs to check for the "The user deleted the last row" case and handle it differently. When you're at the last row, you have two options:
Refresh your existing index path (it should transform into the placeholder cell):
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
[self.tableView endUpdates];
Delete the user's cell and insert the placeholder cell:
[self.tableView beginUpdates];
[self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
[self.tableView insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationLeft];
[self.tableView endUpdates];
Upvotes: 3