iOS 10中UITableView首单元格被导航栏遮挡问题优化方案咨询
解决iOS 10/11弹窗中UITableView适配冲突的无版本判断方案
这个问题我之前也碰到过,核心原因是iOS 11引入了**安全区域(Safe Area)**机制,替代了iOS 10及以下的topLayoutGuide/bottomLayoutGuide,导致手动设置contentInset在两个版本中表现矛盾。不用写版本判断的话,推荐两种更优雅的系统原生适配方案:
方案1:利用自动布局绑定适配容器
放弃手动设置contentInset,通过自动布局直接将UITableView的边缘与视图的适配容器绑定,让系统自动处理不同版本的间距:
在myCustomViewController的viewDidLoad中添加以下代码:
// 关闭tableView的自动转换约束(如果之前用frame布局的话) self.tableView.translatesAutoresizingMaskIntoConstraints = NO; // 创建适配不同iOS版本的顶部约束 NSLayoutConstraint *topConstraint; if (@available(iOS 11.0, *)) { topConstraint = [self.tableView.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor]; } else { topConstraint = [self.tableView.topAnchor constraintEqualToAnchor:self.topLayoutGuide.bottomAnchor]; } // 绑定其他边缘约束 NSLayoutConstraint *leading = [self.tableView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor]; NSLayoutConstraint *trailing = [self.tableView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor]; NSLayoutConstraint *bottom = [self.tableView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor]; // 激活约束 [NSLayoutConstraint activateConstraints:@[topConstraint, leading, trailing, bottom]];
这种方式让系统根据iOS版本自动选择布局参考,既解决iOS10中tableView被导航栏遮挡的问题,又不会在iOS11中产生额外空白。
方案2:利用系统自动调整ScrollView内边距
iOS10及以下可以依靠UIViewController的automaticallyAdjustsScrollViewInsets属性,iOS11则通过Safe Area自动适配,只需要确保以下两点:
- 在
myCustomViewController中开启自动调整:
- (void)viewDidLoad { [super viewDidLoad]; // 默认是YES,若之前被修改过需重新开启 self.automaticallyAdjustsScrollViewInsets = YES; }
- 确保UITableView的顶部边缘与视图的顶部对齐:
// 用frame布局的话 self.tableView.frame = self.view.bounds; // 用自动布局的话,直接绑定到view的topAnchor [self.tableView.topAnchor constraintEqualToAnchor:self.view.topAnchor].active = YES;
这样iOS10会自动为tableView添加等于导航栏高度的contentInset,iOS11则会通过Safe Area自动避开导航栏区域,完美兼容两个版本。
为什么不推荐手动版本判断?
手动判断iOS版本会增加代码维护成本,后续iOS版本更新可能需要再次调整。而利用系统原生的布局API,既能享受版本适配的自动优化,又能让代码更简洁健壮。
内容的提问来源于stack exchange,提问作者Francis F
相关产品推荐
相关产品推荐

