【OC-UITableView】iOS11 设置 heightF

作者: 苜蓿鬼仙 | 来源:发表于2018-07-23 17:31 被阅读2次

    首语

    今天项目中一个需求,具体原型图如下图。


    原始需求图

    需要在设置了 UITableViewUITableViewStyleGrouped 样式后,头部需要设置一个温馨提示的标签。本来实现的方式有多种方式,比如:

    • ① 可以选择通过 tableHeaderView 属性创建一个 UIView,并在其上添加一个 UILabel 即可以实现。
    @property (nonatomic, strong, nullable) UIView *tableHeaderView;  
    // accessory view for above row content. default is nil. not to be confused with section header
    
    • ② 可以选择通过下面方法直接返回 title 即可以实现。
    - (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;    
    // fixed font style. use custom view (UILabel) if you want something different
    
    • ③ 可以通过下面方法直接自定义 viewForHeaderInSection ,并在其上添加一个 UILabel 即可以实现。
    - (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;   
    // custom view for header. will be adjusted to default or specified header height
    

    本以为最多几分钟的事儿,基本上就可以实现了。但是天公如此不作美,发现效果比较骨感,上一下效果图(这里是测试 Demo,只是简例)。

    第一次实现效果图

    备注:
    环境:Xcode 9.4.1,iOS 11.4



    初次实现效果问题

    看看效果,嗯?第一个 sectionHeader 的高度和其他的一样?
    有问题!
    有问题!
    绝对有问题!

    此处上一下写得代码(测试 Demo):

    //
    //  ViewController.m
    //  TestDemo11
    //
    //  Created by 苜蓿鬼仙 on 2018/7/23.
    //  Copyright © 2018 苜蓿鬼仙. All rights reserved.
    //
    
    #import "ViewController.h"
    
    @interface ViewController ()<UITableViewDataSource, UITableViewDelegate>
    
    @property (nonatomic, strong) UITableView *tableView;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        
        self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 64, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height-64) style:UITableViewStyleGrouped];
        self.tableView.backgroundColor = [UIColor lightGrayColor];
        self.tableView.dataSource      = self;
        self.tableView.delegate        = self;
        self.tableView.rowHeight       = 50;
        self.tableView.showsVerticalScrollIndicator = NO;
        [self.view addSubview:self.tableView];
        
        [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"];
    }
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
        return 5;
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
        return 1;
    }
    
    - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
        if (section == 0) {
            return @"温馨提示:左滑列表可以编辑广告";
        }
        return nil;
    }
    
    - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
        if (section == 0) {
            return 40;
        } else {
            return 20;
        }
    }
    
    - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
        return CGFLOAT_MIN;
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
        
        cell.textLabel.text = [indexPath description];
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
        
        return cell;
    }
    
    @end
    

    想想以前也是如此写得呀,貌似没有啥子问题呀,经过调试发现:

    - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
        if (section == 0) {
            return 40;
        } else {
            return 20;
        }
    }
    

    这个方法只调用了一次。

    这就肯定不对了,如果只会调用一次的话,则肯定所有的高度都会和第一个 sectionHeader 的高度相同了。后面又再次调试了一段时间,发现没有灵感,然后向群里的一些大神们求助,发现相同的代码及环境,发现大神们的并没有任何问题,唯一的区别就是大神们是通过 StoryBoard 创建的,我这边则是通过纯代码创建的。

    然后我也尝试通过 StoryBoard 创建了一下,发现问题解决了!!!

    这是闹哪样???逗我呢???肯定有猫腻!!!

    最后经过大神的提醒,发现了一些猫腻,是关于 自动计算(UITableViewAutomaticDimension) 上的问题。



    系统UITableView 的 API

    @property (nonatomic) CGFloat rowHeight;             // default is UITableViewAutomaticDimension
    @property (nonatomic) CGFloat sectionHeaderHeight;   // default is UITableViewAutomaticDimension
    @property (nonatomic) CGFloat sectionFooterHeight;   // default is UITableViewAutomaticDimension
    @property (nonatomic) CGFloat estimatedRowHeight NS_AVAILABLE_IOS(7_0); // default is UITableViewAutomaticDimension, set to 0 to disable
    @property (nonatomic) CGFloat estimatedSectionHeaderHeight NS_AVAILABLE_IOS(7_0); // default is UITableViewAutomaticDimension, set to 0 to disable
    @property (nonatomic) CGFloat estimatedSectionFooterHeight NS_AVAILABLE_IOS(7_0); // default is UITableViewAutomaticDimension, set to 0 to disable
    
    // Variable height support
    
    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
    - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
    - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;
    
    // Use the estimatedHeight methods to quickly calcuate guessed values which will allow for fast load times of the table.
    // If these methods are implemented, the above -tableView:heightForXXX calls will be deferred until views are ready to be displayed, so more expensive logic can be placed there.
    - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(7_0);
    - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForHeaderInSection:(NSInteger)section NS_AVAILABLE_IOS(7_0);
    - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForFooterInSection:(NSInteger)section NS_AVAILABLE_IOS(7_0);
    
    // Section header & footer information. Views are preferred over title should you decide to provide both
    
    - (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;   // custom view for header. will be adjusted to default or specified header height
    - (nullable UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section;   // custom view for footer. will be adjusted to default or specified footer height
    

    从此处可以看到这个系统的 API,默认都是 UITableViewAutomaticDimension 自动计算的模式。

    然后我们再看看 StoryBoard 中这些参数是如何的:

    iOS11 StoryBoard 中 UITableView 高度相关参数

    从此处可以看出 StoryBoard 中,除了 Row Height 是默认 Automatic 自动计算的,Header HeightFooter Height 都不是默认 Automatic 动计算的。

    但是依据上面的系统 API 可以看出,如果是纯代码写得,应该是默认全部都是 Automatic 自动计算的。

    看来问题应该就是出在这里了,赶紧改代码试试。



    解决方案

    @property (nonatomic) CGFloat estimatedSectionHeaderHeight NS_AVAILABLE_IOS(7_0); // default is UITableViewAutomaticDimension, set to 0 to disable
    @property (nonatomic) CGFloat estimatedSectionFooterHeight NS_AVAILABLE_IOS(7_0); // default is UITableViewAutomaticDimension, set to 0 to disable
    
    
    self.tableView.estimatedSectionHeaderHeight = 0;
    self.tableView.estimatedSectionFooterHeight = 0;
    

    estimatedSectionHeaderHeightestimatedSectionFooterHeight 都设置为 0,即可以取消 Automatic 自动计算了。



    最终代码及效果图

    //
    //  ViewController.m
    //  TestDemo11
    //
    //  Created by 苜蓿鬼仙 on 2018/7/23.
    //  Copyright © 2018 苜蓿鬼仙. All rights reserved.
    //
    
    #import "ViewController.h"
    
    @interface ViewController ()<UITableViewDataSource, UITableViewDelegate>
    
    @property (nonatomic, strong) UITableView *tableView;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        
        self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 64, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height-64) style:UITableViewStyleGrouped];
        self.tableView.backgroundColor = [UIColor lightGrayColor];
        self.tableView.dataSource      = self;
        self.tableView.delegate        = self;
        self.tableView.rowHeight       = 50;
        self.tableView.estimatedSectionHeaderHeight = 0;
        self.tableView.estimatedSectionFooterHeight = 0;
        self.tableView.showsVerticalScrollIndicator = NO;
        [self.view addSubview:self.tableView];
        
        [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"];
    }
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
        return 5;
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
        return 1;
    }
    
    - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
        if (section == 0) {
            return @"温馨提示:左滑列表可以编辑广告";
        }
        return nil;
    }
    
    - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
        if (section == 0) {
            return 40;
        } else {
            return 20;
        }
    }
    
    - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
        return CGFLOAT_MIN;
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
        
        cell.textLabel.text = [indexPath description];
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
        
        return cell;
    }
    
    @end
    
    最终效果图

    相关文章

      网友评论

        本文标题:【OC-UITableView】iOS11 设置 heightF

        本文链接:https://www.haomeiwen.com/subject/tlijmftx.html