1

I'm facing a strange problem with my UITableViewController and working with NSIndexPaths. In my UITableView I've implemented a custom OptionCell that fades in below the clicked cell and fades out afterwards. With iOs 4.3 it works flawlessly.

I've recently updated to the new xCode and iOs 6. I changed the relevant points in the project and everything works except of a crash that appears whenever I try to remove the customCell.

It crashes with:

Assertion failure in -[NSIndexPath row]

[...]

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid index path for use with UITableView. Index paths passed to table view must contain exactly two indices specifying the section and row. Please use the category on NSIndexPath in UITableView.h if possible.

I've made some research regarding this error. I found this question, checked the mentioned steps but it didn't help.

While debugging I found out it crashes everytime I check the row of the indexPathToDelete. It is not NIL and should have one (works on old iOs Version). Did they change something with the NSIndexPath in between the versions? I've checked everything I could possible think of...

Screenshot from Debugger last step before the crash

I marked the error in the following code segment:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row == 0) {

        /* if user tapped the same row twice get rid of the OptionCell */
        if([indexPath isEqual:self.tappedIndexPath]){
            [tableView deselectRowAtIndexPath:indexPath animated:YES];
        }

        /* update the indexpath if needed...*/
        indexPath = [self modelIndexPathforIndexPath:indexPath];

        /* pointer to delete the control cell */
        NSIndexPath *indexPathToDelete = self.controlRowIndexPath;

        /* if same row is tapped twice => clear tapping trackers */
        if([indexPath isEqual:self.tappedIndexPath]){
            self.tappedIndexPath = nil;
            self.controlRowIndexPath = nil;
        }
        /* otherwise update them appropriately */
        else{
            self.tappedIndexPath = indexPath; /* the row the user just tapped. */
            /* Now set the location of where I need to add the option cell */
            self.controlRowIndexPath = [NSIndexPath indexPathForRow:indexPath.row + 1 inSection:indexPath.section];
        }

        /* all logic is done, lets start updating the table */
        [tableView beginUpdates];

        /* lets delete the control cell, either the user tapped the same row twice or tapped another row */

        if(indexPathToDelete){



/* CRASH APPEARS HERE!: */



            [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPathToDelete]
                                  withRowAnimation:UITableViewRowAnimationRight];
        }
        /* lets add the new control cell in the right place */
        if(self.controlRowIndexPath){
            [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:self.controlRowIndexPath]
                                  withRowAnimation:UITableViewRowAnimationLeft];
//          [self.tableView scrollToRowAtIndexPath:self.controlRowIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];

        }

        /* and we are done... */
        [tableView endUpdates];
    } else {
        if (self.controlRowIndexPath) {

            indexPath = [self modelIndexPathforIndexPath:indexPath];
            NSIndexPath *indexPathToDelete = self.controlRowIndexPath;
            self.tappedIndexPath = nil;
            self.controlRowIndexPath = nil;
            if(indexPathToDelete){
                [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPathToDelete]
                                      withRowAnimation:UITableViewRowAnimationFade];
            }
        }

        VerwaltungViewController* verwaltungViewController;
        verwaltungViewController = [[VerwaltungViewController alloc] init];
        [self.navigationController pushViewController:verwaltungViewController animated:YES];
    }
}

EDIT: modelIndexPathforIndexPath:

- (NSIndexPath *)modelIndexPathforIndexPath:(NSIndexPath *)indexPath
{
    int whereIsTheControlRow = self.controlRowIndexPath.row;
    if(self.controlRowIndexPath != nil && indexPath.row > whereIsTheControlRow)
        return [NSIndexPath indexPathForRow:indexPath.row - 1 inSection:0];
    return indexPath;
}
Community
  • 1
  • 1
Git.Coach
  • 3,032
  • 2
  • 37
  • 54
  • 1
    From your debugger display, it looks as if there are cases where `indexPathToDelete` is essentially empty: no indexes and a length of zero. Since it's being set from `self.controlRowIndexPath`, how is that defined? Also, you might want to show `modelIndexPathforIndexPath` since it has the ability to change `controlRowIndexPath`. – Phillip Mills Nov 12 '12 at 14:53
  • 1
    The controlRowIndexPath contains the correct Path (+row). If I debug the same code on an SnowLeopard Mac with old xCode and iOs 4.3 I can NSLog the indexPathToDelete and receive 1. Doing it on the newest Version(s) it crashes because row cannot be found... What do you mean by "you want to show modelIndexPathForIndexPath"? – Git.Coach Nov 12 '12 at 15:49
  • 1
    I mean that showing the code for that method might (or might not) give some hints. Something is causing a strange kind of NSIndexPath to be generated and I don't see it in what you've posted but that method could possibly be the catalyst. – Phillip Mills Nov 12 '12 at 15:54
  • I added the function to the post. :) – Git.Coach Nov 13 '12 at 12:13

0 Answers0