How to stop UITableView moveRowAtIndexPath from leaving blank rows upon reordering

Posted by coneybeare on Stack Overflow See other posts from Stack Overflow or by coneybeare
Published on 2010-02-11T05:02:23Z Indexed on 2010/04/26 17:13 UTC
Read the original article Hit count: 605

I am having an issue where in reordering my UITableViewCells, the tableView is not scrolling with the cell. Only a blank row appears and any subsequent scrolling gets an Array out of bounds error without any of my code in the Stack Trace. Here is a quick video of the problem.

Here is the relevant code:

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    return indexPath.section == 1;
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
    BOOL ret = indexPath.section == 1 && indexPath.row < self.count;
    DebugLog(@"canMoveRowAtIndexPath: %d:%d %@", indexPath.section, indexPath.row, (ret ? @"YES" : @"NO"));
    return ret;
}
- (void)delayedUpdateCellBackgroundPositionsForTableView:(UITableView *)tableView {
    [self performSelectorOnMainThread:@selector(updateCellBackgroundPositionsForTableView:) withObject:tableView waitUntilDone:NO];
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
    if (fromIndexPath.row == toIndexPath.row) return;

    DebugLog(@"Moved audio from %d:%d to %d:%d", fromIndexPath.section, fromIndexPath.row, toIndexPath.section, toIndexPath.row);
    NSMutableArray *audio = [self.items objectAtIndex:fromIndexPath.section];
    [audio exchangeObjectAtIndex:fromIndexPath.row withObjectAtIndex:toIndexPath.row];
    [self performSelector:@selector(delayedUpdateCellBackgroundPositionsForTableView:) withObject:tableView afterDelay:kDefaultAnimationDuration/3];
}

And here is the generated Stack Trace of the crash:

Exception Type:  EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000002, 0x0000000000000000
Crashed Thread:  0  Dispatch queue: com.apple.main-thread

Application Specific Information:
iPhone Simulator 3.2 (193.3), iPhone OS 3.0 (7A341)
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSCFArray removeObjectsInRange:]: index (6) beyond bounds (6)'

Thread 0 Crashed:  Dispatch queue: com.apple.main-thread
0   CoreFoundation                  0x302ac924 ___TERMINATING_DUE_TO_UNCAUGHT_EXCEPTION___ + 4
1   libobjc.A.dylib                 0x93cb2509 objc_exception_throw + 56
2   CoreFoundation                  0x3028e5fb +[NSException raise:format:arguments:] + 155
3   CoreFoundation                  0x3028e55a +[NSException raise:format:] + 58
4   Foundation                      0x305684e9 _NSArrayRaiseBoundException + 121
5   Foundation                      0x30553a6e -[NSCFArray removeObjectsInRange:] + 142
6   UIKit                           0x30950105 -[UITableView(_UITableViewPrivate) _updateVisibleCellsNow] + 862
7   UIKit                           0x30947715 -[UITableView layoutSubviews] + 250
8   QuartzCore                      0x0090bd94 -[CALayer layoutSublayers] + 78
9   QuartzCore                      0x0090bb55 CALayerLayoutIfNeeded + 229
10  QuartzCore                      0x0090b3ae CA::Context::commit_transaction(CA::Transaction*) + 302
11  QuartzCore                      0x0090b022 CA::Transaction::commit() + 292
12  QuartzCore                      0x009132e0 CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) + 84
13  CoreFoundation                  0x30245c32 __CFRunLoopDoObservers + 594
14  CoreFoundation                  0x3024503f CFRunLoopRunSpecific + 2575
15  CoreFoundation                  0x30244628 CFRunLoopRunInMode + 88
16  GraphicsServices                0x32044c31 GSEventRunModal + 217
17  GraphicsServices                0x32044cf6 GSEventRun + 115
18  UIKit                           0x309021ee UIApplicationMain + 1157
19  XXXXXXXX                        0x0000278a main + 104 (main.m:12)
20  XXXXXXXX                        0x000026f6 start + 54

NOte that the array out of bounds length is not the length of my elements (I have 9), but always something smaller.

I have been trying to solve this for many hours days without avail… any ideas?



UPDATE: More code as requested
In my delegate:

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
    return UITableViewCellEditingStyleNone;
}

- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath {
    int count = [(UAPlaylistEditDataSource *)self.dataSource count];
    if (proposedDestinationIndexPath.section == 0) {
        return [NSIndexPath indexPathForRow:0 inSection:sourceIndexPath.section];
    }else if (proposedDestinationIndexPath.row >= count) {
        return [NSIndexPath indexPathForRow:count-1 inSection:sourceIndexPath.section];
    }
    return proposedDestinationIndexPath;
}

…thats about it. I am using the three20 framework and I have not had any issues with reordering till now. The problem is also not in the updateCellBackgroundPositionsForTableView: method as it still crashes when this is commented out.

© Stack Overflow or respective owner

Related posts about iphone

Related posts about uitableview