views:

373

answers:

4

Hallo @ All

I ran into the same problem as desciped in http://stackoverflow.com/questions/1884491/crashing-while-trying-to-move-uitableview-rows! All I want to do is on specific reranging operations insert a new cell or delet the selected one!

Sometimes I get a

* Assertion failure in -[_UITableViewUpdateSupport _setupAnimationForReorderingRow], /SourceCache/UIKit/UIKit-963.10/UITableViewSupport.m:295 Attempt to create two animations for cell exception

and when I want to reload my data by calling [self.tableView reloadData] I get a

* Terminating app due to uncaught exception 'NSRangeException', reason: '* -[NSCFArray objectAtIndex:]: index (0) beyond bounds (0)'

This is quiet anoying! Is there anybody out there who knows how to handle this problem?

Please help me!

A: 

Hi again!

Actually I'm trying to delete a row, when it's dragged to the bottom. I keep my data in a mutable array and it's initialized by my initialization method "initData" which is called in the method "viewDidLoad" and reinitialized in the "controllerDidChangeContent:(NSFetchedResultsController *)controller" method.

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
if( fromIndexPath == toIndexPath ) {
    return;
}

id element = [self.data objectAtIndex:fromIndexPath.row];

if (toIndexPath.row == [self.data count] -1) { //element has been dragged to the bottom
    [self.data removeObjectAtIndex:fromIndexPath.row];
    @try {
        [self.tableView beginUpdates];
        [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:fromIndexPath] withRowAnimation:UITableViewRowAnimationBottom];
        [self.tableView endUpdates];
    }
    @catch (NSException * e) {
        NSLog([NSString stringWithFormat:@"Exception thrown while moving tableviewcell to the End of the table \nName: %@; Reason: %@; userInfo: %@", [e name], [e reason], [e userInfo]]);
    }
}
else { //Normal reoder operation
    [self.data removeObjectAtIndex:fromIndexPath.row];
    [self.data insertObject:element atIndex:toIndexPath.row];
}

}

This is my initData method as mentioned before.

-(void) initData {
self.data = [[NSMutableArray alloc] init];

[self.data addObjectsFromArray:[self.fetchedResultsController fetchedObjects]];

}

So I get my displayed elements from the core data, but I can't display the core data because I need to add several elements later. I always have data in my core data (because some elements can't be deleted) and are not removed anywhere else.

Sometimes it works pretty fine. Sometimes i get the "Attempt to create two animations for cell" exception.

Sorry for my previouse post with no code.

And thanks for all in advance for your help!

Nicolay

Nicolay
A: 

http://www.iphonedevsdk.com/forum/iphone-sdk-development/34632-rearranging-uitableview-cell.html

This will help you..

I doubt it will help. It says read the documentation. It would be faster just to have said it here!
Roger
A: 

Hallo again!

Thanks for all your help! I actually found a solution for my problem!

I don't care about animating the tableview while editing anymore! I finally found a solution in this post: http://stackoverflow.com/questions/2242387/how-to-stop-uitableview-moverowatindexpath-from-leaving-blank-rows-upon-reorderin/3021063#3021063

Tom Saxton said:

// APPLE_BUG: if you move a cell to a row that's off-screen (because the destination // has been modified), the bogus cell gets created and eventually will cause a crash

So my code looks like this:

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
if( fromIndexPath == toIndexPath ) {
    return;
}

if (toIndexPath.row == [self.data count] -1) { //element has been dragged to the bottom
        self.data removeObjectAtIndex:fromIndexPath.row];
        [self performSelector:@selector(delayedReloadData:) withObject:tableView afterDelay:0];
}
else { //Normal reoder operation
        [self.data removeObjectAtIndex:fromIndexPath.row];
     [self.data insertObject:element atIndex:toIndexPath.row];
}

}

- (void)delayedReloadData:(UITableView *)tableView {
//Assert(tableView == self.tableView);
[self.tableView reloadData];

}

I also had a mem leak in my initData method, which I solved like this:

-(void) initData {
if (!self.data) {
    self.data = [[NSMutableArray alloc] init];
}
else {
    [self.data removeAllObjects];
}

[self.data addObjectsFromArray:[self.fetchedResultsController fetchedObjects]];

}

Thanks for all your help!

Nikolay

Nicolay
A: 

You still have a mem leak in initData. I assume you defined your data as "@property (nonatomic, retain) NSMutableArray *data". So when you call alloc/init the retain count is 1, and then you assign to self.data which does a retain, giving it a count of 2. You need to do:

NSMutableArray *ary = [[NSMutableArray alloc] init];
self.data = ary;
[ary release];
Scott
Ok, thank you very much!!! I'll consider that.
Nicolay