在没有动画的情况下将行添加到tableview的开头

时间:2015-01-05 09:46:13

标签: ios objective-c uitableview

我想使用begin / endUpdates向tableview添加行,以防止在执行reloadData时跳转tableview

这是我的代码

- (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).

如何防止此错误?

3 个答案:

答案 0 :(得分:2)

如果您不想要动画,请直接使用

- (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];
}

答案 1 :(得分:0)

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

- (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类型)。

答案 2 :(得分:0)

如果您想快速跳转到选定的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];
];

我希望它有所帮助。