基于iOS 11向下适配之总结
这篇文章总结一下项目中遇到的基于iOS 11向下适配时遇到的问题,方便以后查阅。
场景一 (20180425)
创建一个带XIB的UIViewController子类。
XIB中选中Simulated Metrics中的Top Bar为Translucent Navigation Bar
,即告知XIB本页面含有导航栏,如图:
XIB中拖入一个View,设置背景色,设置约束为:宽高各60pt,水平居中,距离Safe Area Top 20pt。如下图:
在 iPhone X 以及其他 iOS 11 机型上运行,显示为预期效果:
在 iOS 9/10 机型上运行显示效果“超出预期”:
解决
给该view添加一个距离Super View Top(即视图控制器的self.view顶部)大于/等于预期间距(20pt)的约束,并设置距离Safe Area Top的约束优先级为750(低于1000)。如图:
在 iOS 9/10 机型运行即可看到预期效果。
分析
优先满足Super View Top约束(优先级1000),其次满足Safe Area Top约束(优先级750)。
当在没有 Safe Area 的机型(iOS 9/10)上运行时,只需要满足Super View Top约束,view距离self.view的top等于84(64 + 20),view在导航栏下面20pt正常显示。
当在有 Safe Area的机型(iOS 11)上运行时,先满足 Super View Top约束,view距离self.view的top大于等于84,再满足距离Safe Area Top 20pt的约束,后者告诉前者应该“大于84”多少(有导航条时,Safe Area的Y坐标零点从导航栏下开始)。
场景二 (20180425更新)
使用XIB创建带 Translucent Navigation Bar 的 ViewController,导航栏的 BarButtonItem 要用代码手动创建。在 iOS 11上,创建一个CustomView的rightBarButtonItem可以这样写:
1 | UIButton *commitButton = [[UIButton alloc] init]; |
在 iOS 11机型上运行,一切正常,但是在 iOS 9/10机型上运行,该BarButtonItem则不会显示。
解决
这里只需要给commitButton设置Frame即可适配 iOS 9/10/11。如下
1 | UIButton *commitButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 44, 44)]; |
分析
原因是 iOS 11的导航条自带AutoLayout,会把未设置Frame的commitButton自动布局。而iOS 9/10的导航条则不自带AutoLayout,Button初始化之后需要设置frame。
场景三 (20180427更新)
ViewController中有已知的三个TableView横向并排排列,并且可以滑动切换。这时,就需要一个ScrollView来做底,UI结构如下图,省略添加约束的过程。
我们知道,IB中的 ScrollView 需要设置 ContentSize 来“撑开”内容,否则 ContentSize 默认为(0, 0)。iOS 9/10 可以在 - (void)viewDidLayoutSubviews
中设置 ScrollView 的 ContentSize,本场景如下:
1 | - (void)viewDidLayoutSubviews { |
但是,iOS 11 中这样设置过 ScrollView 的 ContentSize 之后,ContentSize 仍是(0, 0)。
解决
把设置 ContentSize 的代码写在 - (void)viewDidAppear:(BOOL)animated
中:
1 | - (void)viewDidAppear:(BOOL)animated { |
分析
具体原理未知。
但是经测试发现,在本场景中,- (void)viewWillLayoutSubviews
和- (void)viewDidLayoutSubviews
在 iOS 9/10 中会执行两遍,在 iOS 11 中只会执行一遍,不清楚 Apple 在这之中做了什么修改。
基于iOS 11向下适配之总结