简体   繁体   中英

UITableView crashes when trying to delete a cell and section

I've been working on creating a UITableView that has its content loaded from a NSUserDefaults object. Whenever I attempt to delete a cell/section, however, the program crashes and spits out the following:

*** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-1912.3/UITableView.m:1030
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of sections.  The number of sections contained in the table view after the update (2) must be equal to the number of sections contained in the table view before the update (3), plus or minus the number of sections inserted or deleted (0 inserted, 0 deleted).

No matter how much I read up on this error and try to fix it, I've been stuck here for the past few hours. Here is my method that is called when the user taps the "delete" button:

 (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        //[[[NSUserDefaults standardUserDefaults] objectForKey:@"rawArray"] removeObjectAtIndex:indexPath.row];
        //[[[NSUserDefaults standardUserDefaults] objectForKey:@"rawDates"] removeObjectAtIndex:indexPath.row];

        NSMutableArray *rawArray = [[NSUserDefaults standardUserDefaults] objectForKey:@"rawArray"];
        NSMutableArray *rawDates = [[NSUserDefaults standardUserDefaults] objectForKey:@"rawDates"];

        [rawArray removeObjectAtIndex:indexPath.row];
        [rawDates removeObjectAtIndex:indexPath.row];

        [[NSUserDefaults standardUserDefaults] setObject:rawArray forKey:@"rawArray"];
        [[NSUserDefaults standardUserDefaults] setObject:rawDates forKey:@"rawDates"];

        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
        [tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationRight];

    }    
}

and here are the methods used to determine number of rows and cells:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return [[[NSUserDefaults standardUserDefaults] arrayForKey:@"rawDates"] count];
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{

    return [[[NSUserDefaults standardUserDefaults] arrayForKey:@"rawDates"] objectAtIndex:section];
}

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

The last method in there returns a one because, as of right now, I plan on only have one cell per each section. Thank you for taking the time to look over here, and I really hope you can help me out! :/

Check out the Batch Insertion, Deletion, and Reloading of Rows and Sections

Basically you need to put any calls of these method

- (void)insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
- (void)deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;

- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation: (UITableViewRowAnimation)animation;
- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation: (UITableViewRowAnimation)animation;
- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;

between

- (void)beginUpdates;
- (void)endUpdates;

eg

[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
[tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationRight];
[tableView endUpdates];

Your dataSource also needs to reflect the changes by the time endUpdates is called


Personally I like to make a category to give a block based wrapper around this to

  1. stop me forgetting to call endUpdates
  2. it allows indentation to look right / be automatic

Category on UITableView

@interface UITableView (PSAdditions)

- (void)ps_updates:(void (^)(void))updateBlock;

@end

@implementation UITableView (PSAdditions)

- (void)ps_updates:(void (^)(void))updateBlock;
{
    [self beginUpdates];
    if (updateBlock) { updateBlock(); }
    [self endUpdates];
}

Which would look like this

[tableView ps_updates:^{
    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
    [tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationRight];
}];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM