开发者

App crashing on deleting a row

开发者 https://www.devze.com 2023-03-04 05:55 出处:网络
My table is used to list the rows from the core data. Everything works fine, I have used two types of data to load on the same table view. The data types change on account of the scope button change.

My table is used to list the rows from the core data. Everything works fine, I have used two types of data to load on the same table view. The data types change on account of the scope button change. Two scope buttons one displays completed tasks while other displays pending taks. I can search, update on the table. While only completed list of datas are editable and can be deleted, sometimes it works fine and sometimes it gives error as such,

Serious application error.  An exception was caught from the delegate of 
NSFetchedResultsController during a call to -controllerDidChangeContent:.  *** -
[NSMutableArray insertObject:atIndex:]: index 4 beyond bounds for empty array with 
userInfo (null)

The fetch result controller is initialised as,

- (NSFetchedResultsController *)fetchedResultsControllerWithPredicate:(NSPredicate *)predicate{

if (self.fetchedResultsControl != nil) {
    NSLog(@"Here I am outside");

    return self.fetchedResultsControl;
开发者_开发百科
}

The code to load the cell for tableview is as :

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

static NSString *CellIdentifier = @"Cell";

CustomCell *cell =(CustomCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    NSArray *topLevelObjects=[[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:nil options:nil];
    for (id currentObject in topLevelObjects) {
        if([currentObject isKindOfClass:[UITableViewCell class]]){
            cell=(CustomCell *)currentObject;
            break;
        }
    }

}

[self configureCell:cell atIndexPath:indexPath];
return cell;

}

And the update method called by the NSFetchedResultsControllerDelegate is as;

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
[self.listingTable beginUpdates];
NSLog(@"Changed content");
}

- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <  NSFetchedResultsSectionInfo>)sectionInfo
       atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {

switch(type) {
    case NSFetchedResultsChangeInsert:
        [self.listingTable insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
                      withRowAnimation:UITableViewRowAnimationFade];
        break;

    case NSFetchedResultsChangeDelete:
        [self.listingTable deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
                      withRowAnimation:UITableViewRowAnimationFade];
        break;
}

}

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
   atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
  newIndexPath:(NSIndexPath *)newIndexPath {
NSLog(@"Changed content switch case");
UITableView *tableView = self.listingTable;

switch(type) {

    case NSFetchedResultsChangeInsert:
        [self.listingTable insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                         withRowAnimation:UITableViewRowAnimationTop];
        break;

    case NSFetchedResultsChangeDelete:
        [self.listingTable deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                         withRowAnimation:UITableViewRowAnimationFade];
        break;

    case NSFetchedResultsChangeUpdate:
        [self configureCell:(CustomCell *)[tableView  cellForRowAtIndexPath:indexPath]
                atIndexPath:indexPath];

        break;

    case NSFetchedResultsChangeMove:
      [self.listingTable deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                         withRowAnimation:UITableViewRowAnimationFade];
        [self.listingTable insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                         withRowAnimation:UITableViewRowAnimationFade];
        break;
}
}


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
NSLog(@"Changed Content");
[self.listingTable endUpdates];

}


I don't see any obvious errors but swapping out two logical tables in one tableview is a dangerous design because you have to be very careful that tableview knows that its logical table has been changed.

The error you are getting suggest that the tableview is configuring itself using one the index of one logical table but is actually accessing the array of the second logical table which is shorter.

Your immediate solution it to look closely at the methods like numberOfSections and numberOfRowsInSection to make sure that those update properly when you switched logical tables.

The best design solution is to use two separate tableviews with their own separate data source and then swap them out as needed.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号