ios 无效更新:部分中的行数无效

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29813878/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 05:44:35  来源:igfitidea点击:

Invalid update: invalid number of rows in section

iosxcodeuitableviewcore-dataazure-mobile-services

提问by Sanjay Mohnani

I am working on a project using Microsoft Azure services. In that while deleting a row I am getting this error:

我正在使用Microsoft Azure services. 在删除一行时,我收到此错误:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0.  The number of rows contained in an existing section after the update (2) must be equal to the number of rows 
contained in that section before the update (2), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).

Code for table load and delete row is as :

表加载和删除行的代码如下:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
        return 3;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    //medicine list
    if (section == 0) {
        NSArray *sectionInfo = [self.fetchedResultsController1 fetchedObjects];
        return [sectionInfo count];

    }
    //allergy list
    else if (section == 1) {
        NSArray *sectionInfo = [self.fetchedResultsController2 fetchedObjects];
        return [sectionInfo count];

    }
    //notes list
    else if (section == 2){
        NSArray *sectionInfo = [self.fetchedResultsController3 fetchedObjects];
        return [sectionInfo count];
    }
    else
        return 0;
 }

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

    static NSString *cellIdentifier = @"mcell";
    MedicationTableViewCell *cell = (MedicationTableViewCell *)    [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];

    //  Add utility buttons 
    NSMutableArray *rightUtilityButtons = [NSMutableArray new];
    [rightUtilityButtons sw_addUtilityButtonWithColor: [UIColor colorWithRed:1.0f green:0.231f blue:0.188 alpha:1.0f] title:@"Delete"];

    switch (indexPath.section) {
        case 0: {
            NSManagedObject *item = [self.fetchedResultsController1 objectAtIndexPath:indexPath];
            cell.textLabel.text = [item valueForKey:@"name"];
            break;
        }
        case 1: {
            NSManagedObject *item = [self.fetchedResultsController2 objectAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row inSection:0]];
            cell.textLabel.text = [item valueForKey:@"name"];
            break;
        }
        case 2: {
            NSManagedObject *item = [self.fetchedResultsController3 objectAtIndexPath: [NSIndexPath indexPathForRow:indexPath.row inSection:0]];
            cell.textLabel.text = [item valueForKey:@"title"];
            break;
        }
        default:
            break;
    }
    cell.rightUtilityButtons = rightUtilityButtons;
    cell.delegate = self;

    return cell;
}

- (void)swipeableTableViewCell:(SWTableViewCell *)cell didTriggerRightUtilityButtonWithIndex:(NSInteger)index {

 // Delete button is pressed
 NSIndexPath *cellIndexPath = [self.medicationsTableView indexPathForCell:cell];

 //fetchingg data from local store first
 NSManagedObject *item = [self.fetchedResultsController1 objectAtIndexPath:[NSIndexPath indexPathForRow:cellIndexPath.row inSection:0]];

   NSMutableArray *keys = [[NSMutableArray alloc] initWithObjects:@"id", @"name", @"userId", nil];
   NSMutableArray *values = [[NSMutableArray alloc] initWithObjects: [item valueForKey:@"id"], [item valueForKey:@"name"], [item valueForKey:@"userId"], nil];

    //creating dictionary of data
    NSDictionary *dict = [[NSDictionary alloc] initWithObjects:values forKeys:keys];

    //calling delete fucntion
    [self.authService deleteItem:self.syncTable withDict:dict completion:^{
    //removing row from table view
    [self.medicationsTableView reloadData];
    [self.medicationsTableView deleteRowsAtIndexPaths:@[cellIndexPath] withRowAnimation:UITableViewRowAnimationRight];
      }];
      break;
}

Please tell where I am going wrong. Thanks in advcance!!!!

请告诉我哪里出错了。先谢谢了!!!!

回答by Tapas Pal

In - (void)swipeableTableViewCell: didTriggerRightUtilityButtonWithIndex:

- (void)swipeableTableViewCell: didTriggerRightUtilityButtonWithIndex:

You need to remove either

你需要删除

[self.medicationsTableView reloadData]; 

or

或者

[self.medicationsTableView deleteRowsAtIndexPaths:@[cellIndexPath] withRowAnimation:UITableViewRowAnimationRight];

Because on first line when reloadDataget called it's reload the tableview with new datasource and again calling deleteRowsAtIndexPathstried to delete a rows which already removed by calling reloadDataearlier.

因为在第一行,当reloadData被调用时,它会用新的数据源重新加载 tableview,然后再次调用deleteRowsAtIndexPaths试图删除已经通过调用删除的行reloadData

回答by Sanjay Mohnani

The important thing is that you need to use either

重要的是你需要使用

[self.medicationsTableView reloadData];

or

或者

[self.medicationsTableView deleteRowsAtIndexPaths:@[cellIndexPath] withRowAnimation:UITableViewRowAnimationRight];

The reason being, when the tableview's reload datais called the row which is removed from data source is deleted and after that when the delete row api is called for the same index path(where the row is already deleted causes the issue)

原因是,当tableview's reload data被调用时,从数据源中删除的行被删除,之后当删除行 api 被调用时index path(行已被删除导致问题)

Also just before deleting the row from the table delete the object from the data source (self.fetchedResultsController1) and call

同样在从表中删除行之前,从数据源 ( self.fetchedResultsController1)中删除对象并调用

[self.medicationsTableView deleteRowsAtIndexPaths:@[cellIndexPath] withRowAnimation:UITableViewRowAnimationRight];

and after the above row's deletion animation is completed than you can call(but it is not required)

并且在上述行的删除动画完成后,您可以调用(但不是必需的)

[self.medicationsTableView reloadData];