I've been fighting with tableView deleteRowsAtIndexPaths
of a UITableView
for a week now, and I'm rather desperate...
I have two ViewControllers, in the first one the user selects a few numbers in a UIPickerView
and each time she presses a button the value selected in the pickerview is inserted at index 0 in a NSMutableArray
that is a property of a custom object.
This custom object is both saved (encoded) in NSUserDefaults
and passed through a segue to the second ViewController.
In the second ViewController I have a UITableView
; this second ViewController is both the datasource and delegate for the tableview.
I successfully load all the values of the NSMutableArray
in the tableview.
Everything looks ok in the "add/save/restore from saved" operations: the user can add one or more values in the first ViewController, they're correctly saved to NSUserDefaults
, passed to the second ViewController in the segue, loaded in the cells of the tableview. If I quit the app and launch it again, everything works as expected in both ViewControllers.
My issues start when the user wants to delete a row in the tableview of the second ViewController; doing so obviously updates the custom object in the first ViewController, removing the corresponding object from the mutable array.
I actually can do that, but only for the first 7 / 8 rows of the tableview: when I try to delete a row that is lower in the list (let's say the 15th, 20th) I get an error message like this:
Terminating app due to uncaught exception 'NSRangeException', reason: '* -[__NSArrayM objectAtIndex:]: index 10 beyond bounds [0 .. 9]'
The problem is that, if I trace the values and count of the array (I probably have written a thounsand NSLogs this last week), I'm never "out of range".
While I don't want to bother the community with all my code, maybe an idea of the methods in my app can be useful for a suggestion about the mistakes I must have made...
In the second ViewController:
The number of rows in tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
is the count of the mutable array (self.myObject.myMutableArray.count);
The (reusable) cells in tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
are new instantiations of objects at indexPath.row of the array:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
CustomObject * currentObject = [self.myObject.myMutableArray objectAtIndex:indexPath.row];
I return YES to tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
.
The code of tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
, where I suppose is my problem (the last NSLog I get are inside this method), is:
[self.delegate deleteInMutableArrayOfFirstViewControllerFromTableViewInSecondViewControllerAt:indexPath];
// the first ViewController is the delegate of the second
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
In the first ViewController:
I implement my delegate method deleteInMutableArrayOfFirstViewControllerFromTableViewInSecondViewControllerAt:
//I do a few other things, but the important part should be the removal of the object from
//the array, the passing of the modified object to the second ViewController and the save of
//the data to NSUserDefault using a custom method which I don't write here because it's
//pretty straightforward...
[self.myObject.myMutableArray removeObjectAtIndex:indexPath.row];
[_secondViewController setMyObject:self.myObject];
[self saveToUserDefaults:self.myObject];
I hope the code above is sufficient to get an idea of the problem.
I should point out that I've also tryed to move the call of [self.delegate deleteInMutableArrayOfFirstViewControllerFromTableViewInSecondViewControllerAt:indexPath]
after [tableView beginUpdates]
or after [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]
, but it doesn't fix the issue.
If I understand it correctly, when removing a row in a tableview I should
- Update the object from the original array
- Delete the row of the tableview
in this order... and I think I'm doing just that.
I know that I could try to save every change I do to the array to NSUserDefaults
and save/load the object from that in both ViewControllers, but that looks not elegant at all and it would also force me to rewrite a consistent part of my code (since this second view doesn't contain just the tableview, but also a container of a UIScrollView in which I load 4 child view controllers, each one loading data from the second view controller... that part is working right now I'd hate to risk to break it).
I also considered the possibility that the issue is the reuse of cells, but not instantiating the cells with dequeueReusableCellWithIdentifier
didn't change the odd behavior I'm getting.
As I said, I NSLogged the values (particularly, the count of objects in the NSMutableArray in both ViewControllers) and I seem to always be "inside bounds".
Anyone has a suggestion for me?
Please, consider the fact that I don't always get the error when I delete rows, the crash happens only when deleting rows under the first 7/8.
Thanks in advance!
@cdf1982