Deleterowsatindexpaths Crashing

UITableView deleteRowsAtIndexPaths crash

Reordering the data source array after deleting an item makes no sense if the array is already sorted.

And you must not call deleteRowsAtIndexPaths after reordering the data source array anyway.

This version of commitEditingStyle: is sufficient

-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
VideoItem *video = [historyArray objectAtIndex:indexPath.row];
[[HistoryRepository sharedHistory] removeFromHistories:video];
[historyArray removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}

crash on deleteRowsAtIndexPaths

I've seen this before and it is definitely that you have forgotten to update source of data which fill up table. But that part of code is missing.
The method which caused this is


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return ;
}

deleteRowsATIndexPaths crashing

You have to delete the corresponding record in the tableView's datasource as well.

When you delete a row in the table, the resulting count of rows must match.
Check your tableView.numberOfRowsInSection

iOS Swift: Crash on deleteRowsAtIndexPaths

Before removing cells (or adding) you need to call beginUpdates() on the involved tableView. Then remove, or add cells. When finished, call endUpdates().
Once you call endUpdates(). Remember that once you call endUpdates() your tableView model must be consistent with the number of sections and rows you removed or added.
Begin and End updates allows the ui to present a coherent unique animation for all the cell changes.

tableView.beginUpdates()
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
tableView.endUpdates()

iOS8 Swift: deleteRowsAtIndexPaths crashes

It's easy to reproduce your crash with a Xcode Core Data Master-Detail template project. As a general rule, when you use NSFetchedResultsController, you should really use NSFetchedResultsControllerDelegate (you have declared it but don't use it).

Delete those lines in your tableView:commitEditingStyle:forRowAtIndexPath: method:

tableViewMain.beginUpdates()
tableViewMain!.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: UITableViewRowAnimation.Fade)
tableViewMain.endUpdates()

And add those lines to your viewController class:

func controllerWillChangeContent(controller: NSFetchedResultsController) {
tableViewMain.beginUpdates()
}

func controller(controller: NSFetchedResultsController!, didChangeSection sectionInfo: NSFetchedResultsSectionInfo!, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
switch type {
case .Insert:
tableViewMain.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade)
case .Delete:
tableViewMain.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade)
default:
return
}
}

func controller(controller: NSFetchedResultsController!, didChangeObject anObject: AnyObject!, atIndexPath indexPath: NSIndexPath!, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath!) {
switch type {
case .Insert:
tableViewMain.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Fade)
case .Delete:
tableViewMain.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
case .Update:
return
//Should also manage this case!!!
//self.configureCell(tableView.cellForRowAtIndexPath(indexPath), atIndexPath: indexPath)
case .Move:
tableViewMain.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
tableViewMain.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Fade)
default:
return
}
}

func controllerDidChangeContent(controller: NSFetchedResultsController!) {
tableViewMain.endUpdates()
}

This should fix your problem.

Crash caused by deleteRowsAtIndexPaths

Normally, you'd disable user interaction during animation, but since you'd need a completion handler to know when to turn user interaction back on (table view batch updates don't provide this), you can try posting your batch updates to a block to give the table view a chance to stop churning:

    dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView beginUpdates];
//...
[self.tableView endUpdates];
});

I've solved crashes caused by overlapping batch updates by doing this. I have to say, though, I attempted to reproduce your issue and couldn't. So there might be another issue.

If you still have trouble, consider building your table with TLIndexPathTools. It calculates and performs batch updates for you and is very robust. Specifically to your problem, try running the Settings sample project. Toggling the "Sound" switch on and off rapidly hides and shows a row and doesn't crash.

iOS- deleteRowsAtIndexPaths Crash

It is because you should have a dynamic way of returning the number of rows.

For example, I create an 3 arrays. Each with 3 values (these are NSArray variables) :

In .h file:

NSArray *firstArray;
NSArray *secondArray;
NSArray *thirdArray;

In .m file, viewDidLoad or init or something similar:

firstArray = [NSArray arrayWithObjects:@"Cat", @"Mouse", @"Dog", nil];
secondArray = [NSArray arrayWithObjects:@"Plane", @"Car", @"Truck", nil];
thirdArray = [NSArray arrayWithObjects:@"Bread", @"Peanuts", @"Ham", nil];

When returning number of rows in table, I have :

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return array.count;
if (section == 0) {
return firstArray.count;
} else if (section == 1) {
return secondArray.count;
} else {
return thirdArray.count;
}
}

Then, in cellForRow :

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
}

if (indexPath.section == 0) {
cell.textLabel.text = [firstArray objectAtIndex:indexPath.row];
} else if (indexPath.section == 1) {
cell.textLabel.text = [secondArray objectAtIndex:indexPath.row];
} else {
cell.textLabel.text = [thirdArray objectAtIndex:indexPath.row];
}

return cell;
}

Then I delete @"Dog" by swiping on the table or some other way you want to delete. Then, when reloading the table, your array count will be 2, so the table will "know" that it has to display only 2 rows. Basically, you need to update your data source as well.
It applies for the other sections as well. Because you remove elements from arrays, number of rows will be updated also.

UITableView deleteRowsAtIndexPath crash when delete last record

The problem is that a tableview expects the operations performed on the view to match the data source. You have one record in the table, and you remove it. The tableview is expecting the datasource to now contain zero records, but because of your "no records found" logic, it actually returns a value of 3, hence the consistency error, and your crash.

The bug seems to be this part:

if ([idArray count] == 0) {
[self.idTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}

I assume this was intended to insert the "no records found" row into the table when the last line is deleted, but since your "no records found" actually spans three rows, you need to insert three rows here instead, like this:

if ([idArray count] == 0) {
[self.idTableView insertRowsAtIndexPaths:[NSArray arrayWithObjects:
[NSIndexPath indexPathForRow:0 inSection:indexPath.section],
[NSIndexPath indexPathForRow:1 inSection:indexPath.section],
[NSIndexPath indexPathForRow:2 inSection:indexPath.section],
nil] withRowAnimation:UITableViewRowAnimationFade];
}

For you own sanity however, can I suggest a different approach? Rather than trying to keep your table and datasource in sync whilst juggling these fake three rows of data that are only there for display purposes, why not just insert a UILabel into your view hierarchy (either in front of or behind the tableview) that says "no records found" and show/hide it based on whether the table has any data? That way you can precisely control its position and appearance without having to screw around with your datasource logic.



Related Topics



Leave a reply



Submit