×

UITableView方法的执行顺序流畅性优化

96
朝雨晚风
2017.10.23 17:46* 字数 503

(一)、UITableView的执行顺序

  1. numberOfSectionsInTableView(确定有几组) -> numberOfRowsInSection(确定每组有多少的行) -> heightForRowAtIndexPath(确定每行cell的高度)

  2. 以上信息确定完毕后再依次调用cellForRowAtIndexPath -> heightForRowAtIndexPath

  3. 当滚动获取超出屏幕的cell 会再依次调用 cellForRowAtIndexPath -> heightForRowAtIndexPath

#import "MyTableViewController.h"

@interface MyTableViewController ()

@end

@implementation MyTableViewController

- (void)viewDidLoad {
    [super viewDidLoad];
//    NSLog(@"viewDidLoad");
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
//    NSLog(@"viewWillAppear");
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
//    NSLog(@"viewDidAppear");
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    NSLog(@"---------------------------------");
    NSLog(@"numberOfSections");
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    NSLog(@"numberOfRows");
    return  10;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"reuseIdentifier"];
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"reuseIdentifier"];
    }
    cell.textLabel.text = [NSString stringWithFormat:@"我是第 %ld 行",(long)indexPath.row];
    NSLog(@"cellForRowAtIndexPath");
    return cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"heightForRowAtIndexPath");
    return 100;
}

@end

打印结果:

2017-10-23 15:44:30.834 Test[79696:9847728] ---------------------------------
2017-10-23 15:44:30.834 Test[79696:9847728] numberOfSections
2017-10-23 15:44:30.835 Test[79696:9847728] numberOfRows
2017-10-23 15:44:30.835 Test[79696:9847728] heightForRowAtIndexPath
2017-10-23 15:44:30.835 Test[79696:9847728] heightForRowAtIndexPath
2017-10-23 15:44:30.835 Test[79696:9847728] heightForRowAtIndexPath
2017-10-23 15:44:30.835 Test[79696:9847728] heightForRowAtIndexPath
2017-10-23 15:44:30.835 Test[79696:9847728] heightForRowAtIndexPath
2017-10-23 15:44:30.835 Test[79696:9847728] heightForRowAtIndexPath
2017-10-23 15:44:30.835 Test[79696:9847728] heightForRowAtIndexPath
2017-10-23 15:44:30.835 Test[79696:9847728] heightForRowAtIndexPath
2017-10-23 15:44:30.836 Test[79696:9847728] heightForRowAtIndexPath
2017-10-23 15:44:30.836 Test[79696:9847728] heightForRowAtIndexPath
2017-10-23 15:44:30.840 Test[79696:9847728] ---------------------------------


2017-10-23 15:44:30.842 Test[79696:9847728] cellForRowAtIndexPath
2017-10-23 15:44:30.842 Test[79696:9847728] heightForRowAtIndexPath
2017-10-23 15:44:30.845 Test[79696:9847728] cellForRowAtIndexPath
2017-10-23 15:44:30.845 Test[79696:9847728] heightForRowAtIndexPath
2017-10-23 15:44:30.846 Test[79696:9847728] cellForRowAtIndexPath
2017-10-23 15:44:30.846 Test[79696:9847728] heightForRowAtIndexPath
2017-10-23 15:44:30.846 Test[79696:9847728] cellForRowAtIndexPath
2017-10-23 15:44:30.846 Test[79696:9847728] heightForRowAtIndexPath
2017-10-23 15:44:30.847 Test[79696:9847728] cellForRowAtIndexPath
2017-10-23 15:44:30.847 Test[79696:9847728] heightForRowAtIndexPath


2017-10-23 15:44:30.849 Test[79696:9847728] ---------------------------------
2017-10-23 15:47:59.648 Test[79696:9847728] cellForRowAtIndexPath
2017-10-23 15:47:59.648 Test[79696:9847728] heightForRowAtIndexPath

UITableView的回调顺序是先多次调用tableView:heightForRowAtIndexPath:以确定contentSize及Cell的位置,然后才会调用tableView:cellForRowAtIndexPath:,从而来显示在当前屏幕的Cell。
举个例子来说:如果现在要显示100个Cell,当前屏幕显示5个。那么刷新(reload)UITableView时,UITableView会先调用100次tableView:heightForRowAtIndexPath:方法,然后调用5次tableView:cellForRowAtIndexPath:方法;滚动屏幕时,每当Cell滚入屏幕,都会调用一次tableView:heightForRowAtIndexPath:、tableView:cellForRowAtIndexPath:方法。

(二)、UITableView的流畅性优化

  • 1、 提前计算并缓存好高度(布局),因为heightForRowAtIndexPath:是调用最频繁的方法;
  • 2、异步绘制,遇到复杂界面,遇到性能瓶颈时,可能就是突破口;
  • 3、滑动时按需加载,这个在大量图片展示,网络加载的时候很管用!(SDWebImage已经实现异步加载,配合这条性能杠杠的)。

除了上面最主要的三个方面外,还有很多几乎大伙都很熟知的优化点:

  • 正确使用reuseIdentifier来重用Cells
  • 尽量使所有的view opaque,包括Cell自身
  • 尽量少用或不用透明图层
  • 如果Cell内现实的内容来自web,使用异步加载,缓存请求结果
  • 减少subviews的数量
  • 在heightForRowAtIndexPath:中尽量不使用cellForRowAtIndexPath:,如果你需要用到它,只用一次然后缓存结果
  • 尽量少用addView给Cell动态添加View,可以初始化时就添加,然后通过hide来控制是否显示
iOS 面试理论知识点
Web note ad 1