面试的时候被问到tableView的delegate和DataSource调用顺序问题,以前打过断点调试过,大概记得。回答的是顺序是
numberOfSectionsInTableView
numberOfRowsInSection
heightForRowAtIndexPath
cellForRowAtIndexPath
面试官是个妹子,被她喷的说完全错误,cellForRowAtIndexPath
在heightForRowAtIndexPath
之前调用,说我根本没有断点调试过,当时我也不太确定,后来回来想想不太对,先查查资料,然后写个Demo验证一下。这里只考虑有一个Section的情况。
现在iOS 11.4模拟器上调式一下,在每个代理方法里打印记录
- (void)setup
{
NSLog(@"%@",[[UIDevice currentDevice] systemVersion]);
self.tableView = [[UITableView alloc]initWithFrame:self.view.bounds style:UITableViewStylePlain];
[self.view addSubview:self.tableView];
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"];
self.tableView.delegate = self;
self.tableView.dataSource = self;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
NSLog(@"%s",__FUNCTION__);
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(@"%s",__FUNCTION__);
return 5;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"%s",__FUNCTION__);
return 44;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"%s",__FUNCTION__);
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
cell.textLabel.text = @"Misaki";
return cell;
}
这里可以看到结果
假设一个分区有N个cell,可以看出输出结果的顺序是
for (NSInteger i = 0 ; i < 3 ; i ++ )
{
numberOfSectionsInTableView
numberOfRowsInSection
}
for (NSInteger i = 0 ; i < N ; i ++ )
{
cellForRowAtIndexPath
heightForRowAtIndexPath
heightForRowAtIndexPath
heightForRowAtIndexPath
}
for (NSInteger i = 0 ; i < N ; i ++ )
{
heightForRowAtIndexPath
}
iOS 9.2
然后再iOS 9.2模拟器上看(后来测试过 iOS 9和iOS 10是一样的效果)
执行顺序是
for (NSInteger i = 0 ; i < 3 ; i ++ )
{
numberOfSectionsInTableView
numberOfRowsInSection
for (NSInteger j = 0 ; j < N ; j ++ )
{
heightForRowAtIndexPath
}
}
for (NSInteger i = 0 ; i < N ; i ++ )
{
cellForRowAtIndexPath
heightForRowAtIndexPath
heightForRowAtIndexPath
}
造成iOS 11和以前不一样的是iOS 11默认开启了Self-Sizing
,cell的估高estimatedRowHeight
从0变成UITableViewAutomaticDimension
。只要我们把估高设置为0,就关闭了Self-Sizing
。发现调用顺序和iOS 9调用顺序一样了。
self.tableView.estimatedRowHeight = 0;
实际上Self-Sizing
是iOS 8.0的新特性,但是没有默认开启,iOS 8.0之前是设置不定高的cell是需要手动计算高度的。Self-Sizing
是自动计算行高,需要注意的是要设置tableView的估高estimatedRowHeight
(不可为0),然后将tableView的rowHeight
设置为UITableViewAutomaticDimension
。