tableView delegate方法执行顺序

面试的时候被问到tableView的delegate和DataSource调用顺序问题,以前打过断点调试过,大概记得。回答的是顺序是

numberOfSectionsInTableView
numberOfRowsInSection
heightForRowAtIndexPath
cellForRowAtIndexPath

面试官是个妹子,被她喷的说完全错误,cellForRowAtIndexPathheightForRowAtIndexPath之前调用,说我根本没有断点调试过,当时我也不太确定,后来回来想想不太对,先查查资料,然后写个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;
}

这里可以看到结果

屏幕快照 2018-06-05 下午10.40.22.png

假设一个分区有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是一样的效果)

屏幕快照 2018-06-05 下午10.14.57.png

执行顺序是

    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

你可能感兴趣的:(tableView delegate方法执行顺序)