Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS : Inserting multiple rows in UITableview with insertRowsAtIndexPaths

I have already 10 rows in TableView What I am trying to do is adding another 10 rows for that I am using insertRowsAtIndexPaths but I am getting errors.

Following is the code I am using

-(void)insertDownloadedActions:(NSMutableArray *)dataToAdd
{
        __weak CurrentViewController *weakSelf = self;

        int64_t delayInSeconds = 2.0;
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
        dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
            [weakSelf.tableView beginUpdates];
            [weakSelf.dataSource addObjects:dataToAdd];
            NSIndexPath *newIndexPath = [NSIndexPath indexPathForRow:[weakSelf.dataSource count]-dataToAdd.count-1 inSection:0];
            [weakSelf.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationTop];
            [weakSelf.tableView endUpdates];
        });
}

But I am getting following error for that

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 (20) must be equal to the number of rows contained in that section before the update (10), plus or minus the number of rows inserted or deleted from that section (1 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).
like image 823
Abhishek Avatar asked Jan 08 '14 05:01

Abhishek


2 Answers

The code is close, but the table view needs to be updated with index paths in exact correspondence with what's added to the datasource.

-(void)insertDownloadedActions:(NSMutableArray *)dataToAdd
{
    // don't need this
    //__weak CurrentViewController *weakSelf = self;

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

        // build the index paths for insertion
        // since you're adding to the end of datasource, the new rows will start at count
        NSMutableArray *indexPaths = [NSMutableArray array];
        NSInteger currentCount = self.datasource.count;
        for (int i = 0; i < dataToAdd.count; i++) {
            [indexPaths addObject:[NSIndexPath indexPathForRow:currentCount+i inSection:0]];
        }

        // do the insertion
        [self.dataSource addObjects:dataToAdd];

        // tell the table view to update (at all of the inserted index paths)
        [self.tableView beginUpdates];
        [self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationTop];
        [self.tableView endUpdates];
    });
}

You want a weakSelf to avoid cycle where the block owner retains the block and the block (by using the block owner "self") retains the owner. There's no need for the weakSelf pattern here since the view controller is not retaining a copy of the dispatched block.

like image 168
danh Avatar answered Oct 21 '22 15:10

danh


In swift, to add multiple rows, We can do

let indexPaths = (0 ..< messageList.count).map { IndexPath(row: $0, section: 0) }
self.chatTableView.beginUpdates()
self.chatTableView.insertRows(at: indexPaths, with: .bottom)
self.chatTableView.endUpdates()

Here I'm inserting to indexPath:0 as I want to append the list on scrolling up. (Reverse pagination)

like image 35
ceekay Avatar answered Oct 21 '22 14:10

ceekay