将行添加到没有动画的表视图的开头

Add rows to the beginning of a tableview without animation

我想用 begin/endUpdates 向表视图添加行,以防止在我重新加载数据时表视图跳转

这是我的代码

- (void)updateTableWithNewRowCount:(NSInteger)rowCount
                        andNewData:(NSArray *)newData {
  // Save the tableview content offset
  CGPoint tableViewOffset = [self.messagesTableView contentOffset];

  // Turn of animations for the update block
  // to get the effect of adding rows on top of TableView
  [UIView setAnimationsEnabled:NO];

  [self.messagesTableView beginUpdates];

  NSMutableArray *rowsInsertIndexPath = [[NSMutableArray alloc] init];

  int heightForNewRows = 0;

  for (NSInteger i = 0; i < rowCount; i++) {

    NSIndexPath *tempIndexPath = [NSIndexPath indexPathForRow:i inSection:0];
    [rowsInsertIndexPath addObject:tempIndexPath];
//    [self.messages insertObject:[newData objectAtIndex:i] atIndex:i];
      [self addMessage:[newData objectAtIndex:i]];

    heightForNewRows =
        heightForNewRows + [self heightForCellAtIndexPath:tempIndexPath];
  }

  [self.messagesTableView insertRowsAtIndexPaths:rowsInsertIndexPath
                                withRowAnimation:UITableViewRowAnimationNone];

  tableViewOffset.y += heightForNewRows;

  [self.messagesTableView endUpdates];

  [UIView setAnimationsEnabled:YES];

  [self.messagesTableView setContentOffset:tableViewOffset animated:NO];
}

有时(不是每次)我都会收到此错误

 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 (2 inserted, 0 deleted) and plus or minus the number of
 rows moved into or out of that section (0 moved in, 0 moved  out).

如何防止此错误?

试试这个,我不确定这是否有效。

- (void)updateTableWithNewRowCount:(NSInteger)rowCount
                        andNewData:(NSArray *)newData {
  // Save the tableview content offset
  CGPoint tableViewOffset = [self.messagesTableView contentOffset];

  // Turn of animations for the update block
  // to get the effect of adding rows on top of TableView
  [UIView setAnimationsEnabled:NO];

  NSMutableArray *rowsInsertIndexPath = [[NSMutableArray alloc] init];

  int heightForNewRows = 0;

  for (NSInteger i = 0; i < rowCount; i++) {

    NSIndexPath *tempIndexPath = [NSIndexPath indexPathForRow:i inSection:0];
    [rowsInsertIndexPath addObject:tempIndexPath];
//    [self.messages insertObject:[newData objectAtIndex:i] atIndex:i];
      [self addMessage:[newData objectAtIndex:i]];

    heightForNewRows = heightForNewRows + [self heightForCellAtIndexPath:tempIndexPath];
  }

  tableViewOffset.y += heightForNewRows;
  [UIView setAnimationsEnabled:YES];

  [self.messagesTableView setContentOffset:tableViewOffset animated:NO];

  double delayInSeconds = 1.0;
  dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
  dispatch_after(popTime, dispatch_get_main_queue(), ^(void){

     [self.messagesTableView beginUpdates];
     [self.messagesTableView insertRowsAtIndexPaths:rowsInsertIndexPath
                                   withRowAnimation:UITableViewRowAnimationNone];
     [self.messagesTableView endUpdates];
  });
}

注意:您可能需要更新 rowsInsertIndexPath 引用以在块内使用(__block 类型)。

如果你不想要动画就直接使用

- (void)updateTableWithNewRowCount:(NSInteger)rowCount
                        andNewData:(NSArray *)newData {
  // Save the tableview content offset
  CGPoint tableViewOffset = [self.messagesTableView contentOffset];

  // Turn of animations for the update block
  // to get the effect of adding rows on top of TableView

  NSMutableArray *rowsInsertIndexPath = [[NSMutableArray alloc] init];

  int heightForNewRows = 0;

  for (NSInteger i = 0; i < rowCount; i++) {

    NSIndexPath *tempIndexPath = [NSIndexPath indexPathForRow:i inSection:0];
    [rowsInsertIndexPath addObject:tempIndexPath];
//    [self.messages insertObject:[newData objectAtIndex:i] atIndex:i];
      [self addMessage:[newData objectAtIndex:i]];

    heightForNewRows =
        heightForNewRows + [self heightForCellAtIndexPath:tempIndexPath];
  }

  tableViewOffset.y += heightForNewRows;

  [self.messagesTableView reloadData];

  [self.messagesTableView setContentOffset:tableViewOffset animated:NO];
}

如果想快速跳转到选定的indexPath(带动画或不带动画),可以使用这个功能:

//My function to populate
//tableView is synthesized
-(void)setNewMessage:(NSString*)message{
    // ...
    NSIndexPath *selectedIndexPath = [tableView indexPathForSelectedRow];
    // if your selectedIndexPath==nil, the table scroll stay in the same position
    [self reloadData:selectedIndexPath animated:NO];
}

//My reload data wrapper
-(void)reloadData:(NSIndexPath *)selectedIndexPath animated:(BOOL)animated{
    [tableView reloadData];
    // atScrollPosition can receive different parameters (eg:UITableViewScrollPositionMiddle) 
    [tableView scrollToRowAtIndexPath:selectedIndexPath
                     atScrollPosition:UITableViewScrollPositionTop
                             animated:animated];
}

有一次我在 tableView 中需要同样的灵活性,而这个功能满足了我的需求。您不需要 "setAnimationsEnabled",只需使用:

[tableView scrollToRowAtIndexPath:nil
                 atScrollPosition:UITableViewScrollPositionNone
                         animated:NO];
];

希望对您有所帮助。