gonso
gonso

Reputation: 2085

iPhone dev: editing grouped UITableView

We are about to submit an application to the App store and we have encountered a very odd error when deleting rows and sections in a table.

So far, and for compatibility shake we've been linking with 2.0 (so that any iPhone could run our code).

For that scenario, we have a group table that allows removing items and this is how we handle item removal:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the row from the data source
        NSMutableArray* sect = (NSMutableArray*)[tableContents objectAtIndex:indexPath.section];
        [sect removeObjectAtIndex:indexPath.row];
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];

        //if the section is empty remove it
        if ([sect count] == 0){
            [tableContents removeObjectAtIndex:indexPath.section];
            [tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationFade];
        }

        [tableView reloadData];
    }   
}

This little code works quite well but we have a problem whit section titles. When you delete the last row (the last row left) in a section, that section title remains in the view, floating in the middle of nowhere.

What are we missing?

Thanks in advance

Gonso.

After adding beginUpdate/endUpdates I got a EXC_BAD_ACCES and this output in the console:

#0  0x30beae79 in -[UITableViewRowData rectForFooterInSection:] ()
#1  0x30a9f02d in -[UITableView(_UITableViewPrivate) _updateWithItems:withOldRowData:oldRowRange:newRowRange:] ()
#2  0x30a9a541 in -[UITableView(_UITableViewPrivate) _endCellAnimations] ()
#3  0x0000276a in -[RootViewController tableView:commitEditingStyle:forRowAtIndexPath:] (self=0x5248c0, _cmd=0x30c620b0, tableView=0x528c40, editingStyle=UITableViewCellEditingStyleDelete, indexPath=0x52e6e0) at /Users/MacAdmin/Documents/ws/LabTest/TableViewDeletes/Classes/RootViewController.m:135
#4  0x30a9886c in -[UITableView(UITableViewInternal) animateDeletionOfRowWithCell:] ()
#5  0x30b06d40 in -[UIRemoveControl _doRemove:] ()
#6  0x30a4eee6 in -[UIApplication sendAction:to:from:forEvent:] ()
#7  0x30ab0d36 in -[UIControl sendAction:to:forEvent:] ()
#8  0x30ab11fe in -[UIControl(Internal) _sendActionsForEvents:withEvent:] ()
#9  0x30ab0544 in -[UIControl touchesEnded:withEvent:] ()
#10 0x30a7dc73 in -[UIScrollView touchesEnded:withEvent:] ()
#11 0x30a96a9f in -[UITableView touchesEnded:withEvent:] ()
#12 0x30a67917 in -[UIWindow sendEvent:] ()
#13 0x30a56fff in -[UIApplication sendEvent:] ()
#14 0x30a561e0 in _UIApplicationHandleEvent ()
#15 0x31565dea in SendEvent ()
#16 0x3156840c in PurpleEventTimerCallBack ()
#17 0x9200d615 in CFRunLoopRunSpecific ()
#18 0x9200dcf8 in CFRunLoopRunInMode ()
#19 0x31566600 in GSEventRunModal ()
#20 0x315666c5 in GSEventRun ()
#21 0x30a4eca0 in -[UIApplication _run] ()
#22 0x30a5a09c in UIApplicationMain ()
#23 0x00001fb0 in main (argc=1, argv=0xbfffee88) at /Users/MacAdmin/Documents/wsPogo/LabTest/TableViewDeletes/main.m:14

This is the final code, working if you link for 2.0 ONLY.

if (editingStyle == UITableViewCellEditingStyleDelete) {
    // Delete the row from the data source
        NSMutableArray* sect = (NSMutableArray*)[tableContents objectAtIndex:indexPath.section];
        [sect removeObjectAtIndex:indexPath.row];
        //if its the last row left in the section, just delete the section.
        //if the section is empty remove it
        if ([sect count] == 0){
            [tableContents removeObjectAtIndex:indexPath.section];
            [tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationFade];
        } else {
            //section is not empty, just remove the row
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];
        }
        [tableView reloadData];
}   

Thanks!

Upvotes: 0

Views: 7580

Answers (2)

bourne
bourne

Reputation: 1

You can't delete a row and a section at the same time. Try this:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the row from the data source
        NSMutableArray* sect = (NSMutableArray*)[tableContents objectAtIndex:indexPath.section];
        [tableView beginUpdates];
        if ([sect count] == 1)
        {
            [tableContents removeObjectAtIndex:indexPath.section];
            [tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationFade];
        }
        else{
            [sect removeObjectAtIndex:indexPath.row];
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];
        }
        [tableView endUpdates];

    }   
}

Upvotes: 0

Massimo Cafaro
Massimo Cafaro

Reputation: 25429

I'm not sure if this works on 2.0 since I am using directly 3.0 and now 3.1 beta, but you can try as follows, surrounding your row/section deletions within a beginUpdates/endUpdates block. If this works for you on 2.0, be sure to read the documentation related to these methods to understand exactly what you are allowed to do inside such a block and what is instead strictly forbidden. Note indeed, that I have moved your model updates before the block. Hope this helps.

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the row from the data source
        NSMutableArray* sect = (NSMutableArray*)[tableContents objectAtIndex:indexPath.section];
        [sect removeObjectAtIndex:indexPath.row];
        if ([sect count] == 0)
            [tableContents removeObjectAtIndex:indexPath.section];

        [tableView beginUpdates]
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];

        //if the section is empty remove it
        if ([sect count] == 0){
                [tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationFade];
        }
        [tableView endUpdates]

        [tableView reloadData];
    }   
}

Upvotes: 2

Related Questions