iOS11 Swift4中给UIScrollView添加子ViewController无法占满高度
嗨,我来帮你排查这个问题~你遇到的情况确实和iOS11引入的**安全区域(Safe Area)**以及UIScrollView的新特性有关,咱们一步步来解决:
问题根源分析
在iOS10及更早版本中,UIScrollView不会自动调整内边距来适配状态栏、导航栏这些系统元素;但iOS11开始,UIScrollView新增了contentInsetAdjustmentBehavior属性,默认值是.automatic——它会自动给scrollView添加额外的内边距,导致你手动设置的子VC视图frame高度被压缩,出现蓝色的scrollView露出区域。另外,你用frame硬编码布局的方式,也没法适配iOS11后的安全区域规则。
具体解决方案
方案一:快速禁用scrollView的自动内边距调整
这是最直接的临时修复方案,在你设置contentSize的代码后面加上一行:
self.mainScrollView.contentInsetAdjustmentBehavior = .never
这个设置会让scrollView完全遵循你手动定义的contentSize,不再自动添加内边距,子VC的视图就能占满整个scrollView高度了。
方案二:改用AutoLayout约束布局(更推荐)
用frame硬编码布局在自适应场景下很容易出问题,尤其是iOS11后的安全区域适配,建议换成AutoLayout约束来管理子VC视图:
- 先删除所有设置frame的代码,然后给每个子VC的视图添加约束:
// 配置TrendViewController的约束 NSLayoutConstraint.activate([ trendView.view.topAnchor.constraint(equalTo: mainScrollView.topAnchor), trendView.view.leadingAnchor.constraint(equalTo: mainScrollView.leadingAnchor), trendView.view.widthAnchor.constraint(equalTo: mainScrollView.widthAnchor), trendView.view.heightAnchor.constraint(equalTo: mainScrollView.heightAnchor) ]) // 配置HomeViewController的约束 NSLayoutConstraint.activate([ homeView.view.topAnchor.constraint(equalTo: mainScrollView.topAnchor), homeView.view.leadingAnchor.constraint(equalTo: trendView.view.trailingAnchor), homeView.view.widthAnchor.constraint(equalTo: mainScrollView.widthAnchor), homeView.view.heightAnchor.constraint(equalTo: mainScrollView.heightAnchor) ]) // 配置SearchViewController的约束 NSLayoutConstraint.activate([ searchView.view.topAnchor.constraint(equalTo: mainScrollView.topAnchor), searchView.view.leadingAnchor.constraint(equalTo: homeView.view.trailingAnchor), searchView.view.widthAnchor.constraint(equalTo: mainScrollView.widthAnchor), searchView.view.heightAnchor.constraint(equalTo: mainScrollView.heightAnchor), searchView.view.trailingAnchor.constraint(equalTo: mainScrollView.trailingAnchor) ])
- 这样设置后,你不需要再手动设置
scrollView.contentSize——AutoLayout会自动根据子视图的约束计算出正确的滚动范围,同时完美适配安全区域。
额外检查项
- 如果你的项目还需要兼容iOS11以前的版本,记得在主VC里设置:
self.automaticallyAdjustsScrollViewInsets = false
这个属性是iOS11以前用来控制scrollView内边距的,和iOS11的contentInsetAdjustmentBehavior作用类似,一起设置能避免版本兼容问题。
- 检查子VC的nib文件:如果不需要适配安全区域,可以关闭nib中的「Use Safe Area Layout Guides」选项,避免子视图被自动添加安全区域约束。
至于你提到的旧项目没问题,正是因为旧项目没有启用安全区域布局,或者已经提前禁用了scrollView的自动内边距调整,所以不会受到iOS11新特性的影响。
内容的提问来源于stack exchange,提问作者user1523505

