iOS:使用insertRowsAtIndexPaths在UITableview中插入多行

时间:2014-01-08 05:18:50

标签: ios iphone objective-c uitableview

我在TableView中已有10行我想要做的是添加另外10行,因为我使用的是insertRowsAtIndexPaths,但是我收到了错误。

以下是我正在使用的代码

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

但是我收到了关于

的错误
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).

4 个答案:

答案 0 :(得分:23)

代码很接近,但是表视图需要使用与添加到数据源的内容完全对应的索引路径进行更新。

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

你想要一个weakSelf来避免块所有者保留块的循环,并且块(通过使用块所有者“self”)保留所有者。这里不需要weakSelf模式,因为视图控制器没有保留调度块的副本。

答案 1 :(得分:2)

insertRowsAtIndexPaths:withRowAnimation:以及数据模型的更改都需要在 beginUpdatesendUpates

之间进行

我创建了一个应该独立工作的简单示例。因为找不到任何简单的例子,我花了一周的时间来解决这个问题,所以我希望这能节省时间和头痛!

@interface MyTableViewController ()
@property (nonatomic, strong) NSMutableArray *expandableArray;
@property (nonatomic, strong) NSMutableArray *indexPaths;
@property (nonatomic, strong) UITableView *myTableView;
@end

@implementation MyTableViewController

- (void)viewDidLoad
{
    [self setupArray];
}

- (void)setupArray
{
    self.expandableArray = @[@"One", @"Two", @"Three", @"Four", @"Five"].mutableCopy;
}

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

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.expandableArray.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    //here you should create a cell that displays information from self.expandableArray, and return it
}

//call this method if your button/cell/whatever is tapped
- (void)didTapTriggerToChangeTableView
{
    if (/*some condition occurs that makes you want to expand the tableView*/) {
        [self expandArray]
    }else if (/*some other condition occurs that makes you want to retract the tableView*/){
        [self retractArray]
    }
}

//this example adds 1 item
- (void)expandArray
{
    //create an array of indexPaths
    self.indexPaths = [[NSMutableArray alloc] init];
    for (int i = theFirstIndexWhereYouWantToInsertYourAdditionalCells; i < theTotalNumberOfAdditionalCellsToInsert + theFirstIndexWhereYouWantToInsertYourAdditionalCells; i++) {
        [self.indexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
    }

    //modify your array AND call insertRowsAtIndexPaths:withRowAnimation: INBETWEEN beginUpdates and endUpdates
    [self.myTableView beginUpdates];
    //HERE IS WHERE YOU NEED TO ALTER self.expandableArray to have the additional/new data values, eg:
    [self.expandableArray addObject:@"Six"];
    [self.myTableView insertRowsAtIndexPaths:self.indexPaths withRowAnimation:(UITableViewRowAnimationFade)];  //or a rowAnimation of your choice

    [self.myTableView endUpdates];
}

//this example removes all but the first 3 items
- (void)retractArray
{
    NSRange range;
    range.location = 3;
    range.length = self.expandableArray.count - 3;

    //modify your array AND call insertRowsAtIndexPaths:withRowAnimation: INBETWEEN beginUpdates and endUpdates
    [self.myTableView beginUpdates];
    [self.expandableArray removeObjectsInRange:range];
    [self.myTableView deleteRowsAtIndexPaths:self.indexPaths withRowAnimation:UITableViewRowAnimationFade];  //or a rowAnimation of your choice
    [self.myTableView endUpdates];
}

@end

免费代码,不要敲它。

答案 2 :(得分:1)

很快,要添加多行,我们可以做

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

在这里,我要插入到indexPath:0,因为我想在向上滚动时追加列表。 (反向分页)

答案 3 :(得分:0)

我不确定这一点,但尝试这可能会解决您的问题,这可能是您在调用开始更新后添加数据的问题。因此,只需在开始更新之前更新数据源。