为什么UITableView reloadData不能用于动画块?

时间:2016-12-29 07:56:34

标签: ios objective-c uitableview reloaddata

之前,我不知道为什么,当我reloadData我的桌子时,需要很长时间。

enter image description here

我有测试Log来证明,显示慢不是因为网络:

2016-12-29 14:50:20.958 Eee[1572:25220] lml-info-vc-test-net-began
2016-12-29 14:50:20.958 Eee[1572:25220] lml-info-vc-test-net-end
2016-12-29 14:50:20.972 Eee[1572:25220] lml-info-vc-test-net-animations-reloadData-bigin
2016-12-29 14:50:34.870 Eee[1572:25220] lml-info-vc-test-net-animations-reloadData-end

正如我们所见, net-started net-end 只需要很少的时间。
reloadData-bigin reloadData-end 需要很长时间,所以我搜索了SO,reloadData做了什么?我想深刻了解,不是简单的回答,我搜索的总是简单的答案,而不是深入分析。

我的reloadData代码:

//[self.pre_tableView reloadData];
[UIView animateWithDuration:0 animations:^{

     NSLog(@"lml-info-vc-test-net-animations-reloadData-bigin");

     [self.pre_tableView reloadData];
     NSLog(@"lml-info-vc-test-net-animations-reloadData-end");
 } completion:^(BOOL finished) {
     //Do something after that...
     [_pre_tableView.mj_footer endRefreshing];
     [_pre_tableView.mj_header endRefreshing];

 }];

我使用动画块,并在completionHadler中结束刷新。

我还搜索了苹果docs for reloadData

在讨论中:

  

调用此方法重新加载用于构造表的所有数据,包括单元格,节页眉和页脚,索引数组等。为了提高效率,表视图仅重新显示可见的行。如果表因重新加载而缩小,它会调整偏移量。表视图的委托或数据源在希望表视图完全重新加载其数据时调用此方法。它不应该在插入或删除行的方法中调用,尤其是在通过调用beginUpdates和endUpdates实现的动画块中。

注意

用细心的句子:

  

不应在插入或删除行的方法中调用它,尤其是在动画块

嘛!这意味着我不应该使用UIView animateWithDuration方法reloadData,所以我将代码替换为以下代码:

[self.pre_tableView reloadData];
[_pre_tableView.mj_footer endRefreshing];
[_pre_tableView.mj_header endRefreshing];

现在它不再慢了。很高兴,我找到了原因。

但是,我只是想知道为什么,为什么不能将reloadData方法放在动画块中?

并且它reloadData没有失败,即使需要很长时间,在动画块发生了什么?那么这里需要这么多时间?

修改-1

我的附加代码如下:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    return self.pre_dataSource.count;
}

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

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:info_TableIdentifier];

    if (cell == nil) {

        cell = [[LMLAgricultureTechCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:info_TableIdentifier];
    }
    //NSLog(@"lml-info-vc-test-cellSetModel-began");
    ((LMLAgricultureTechCell *)cell).model = self.pre_dataSource[indexPath.row];
    //NSLog(@"lml-info-vc-test-cellSetModel-end");
    ((LMLAgricultureTechCell *)cell).indexPath = indexPath;
    ((LMLAgricultureTechCell *)cell).delegate = self;
    ((LMLAgricultureTechCell *)cell).photo_view.delegate = self;

    return cell;

}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // >>>>>>>>>>>>>>>>>>>>> * cell自适应 * >>>>>>>>>>>>>>>>>>>>>>>>
    id model;

    model = self.pre_dataSource[indexPath.row];

    return [self.pre_tableView cellHeightForIndexPath:indexPath model:model keyPath:@"model" cellClass:[LMLAgricultureTechCell class] contentViewWidth:[self cellContentViewWith]];
}

1 个答案:

答案 0 :(得分:1)

UIView.animateWithDuration...方法只能为animatable的值设置动画。虽然它有时候感觉像魔术 - 它并不是真的...... reloadData是一种异步方法,无法由动态的animate块处理。

如果您想要设置转换动画,可以使用insert/delete/moveRows或使用UIView的{​​{3}}方法。此方法将在屏幕外完全呈现视图,因为它将查看您在其中放置的所有更改,而不是在视图的当前状态和新呈现的视图之间进行动画传输。动画本身取决于您提供的选项,您可能希望使用UIViewAnimationOptionsTransitionCrossDissolve

[UIView transitionWithView:self.pre_tableView 
              duration:0.3 
               options:UIViewAnimationOptionsTransitionCrossDissolve 
            animations: ^{ 
                [self.pre_tableView reloadData];
            } completion: ^(BOOL finished) { 
                ... 
            }];