我为什么要说UIStackView在iOS11上可能会影响子试图的布局呢?因为我大概找到了因为 UIStackView 而引发出来的问题,没有找到问题的关键所在,也没有找到解决方法。

事情大概是这个样子的,我因为要做一款个人的 APP,就借鉴了一下滴滴出行的 UI 界面,设计成下面的样子。

5D870329-235A-447B-81AE-0CE4C72CFCEE

当时就准备把下面的做成一个控件

5365C951-77C0-4A2B-886E-9A827CD183AA

我说干就那就干,立马在 Github 立项,开始风风火火的制作起来。(这就是我的 Github 那么多废弃的坑了)

https://github.com/Share-Parking/ShareParking-Swich

大家可以前往 developer 分支查看此项目的进度,为了更加方便封装。我使用了 Framework 的方式来做这个控件。

使用 Framework 这种方式其实有几个好处的,我慢慢的说一下究竟有哪些好处。

  1. 可以支持 Playground 进行界面的边写边调试
  2. 支持 Swift 转换成 OC 在 OC 工程运行
  3. 可以使用 Carthage 很方便的打包成 Framework 接入 Carthage和 Cocoapods
  4. 可以一边练习 Swift 一边写轮子

唯一的缺点是不支持 iOS8以下,没事我这个轮子还不支持 iOS9以下呢?

起先在我 Playground 运行显示和交互十分的正常,但是在例子里面就表现的不正常了。

我觉得这个不正常应该来源于我的习惯,如果不是因为我的习惯,绝对还发现不了。

我的习惯测试控件都喜欢把初始的位置设置到(0,0)。

下面是我测试代码

let swich = SPSwich(frame: CGRect(x: 0, y: 0, width: 200, height: 100))
self.view.addSubview(swich)

这两句代码是我从 Playground直接拷贝过来的,Playground 表现的结果如下。

2017-12-20 15_32_36

但是同样的代码放在我的例子上面就表现成下面的样子了。

2017-12-20 15_34_34

我们可以看到当我们进行切换的时候,我们的试图明显的被挤压了。我们目测被挤压的高度应该是20高度。

为什么会被20高度呢?20高度代表着什么呢?

一个大胆的想法出现在我的脑海里面,那就是是不是20代表着状态栏的高度,如果我们设置的位置在导航栏的下面,就可以不偏移了。

我带着半信半疑的态度,立马把代码设置成下面的样子。

let swich = SPSwich(frame: CGRect(x: 0, y: 20, width: 200, height: 100))
self.view.addSubview(swich)
2017-12-20 15_39_30

果然验证了我的猜想,但是为什么突然就出现影响子试图的位置和大小了呢?

我们之前如果想设置全屏的布局就需要设置一个属性,那就是下面的代码。

self.automaticallyAdjustsScrollViewInsets = false

但是不幸的是这个属性竟然在 iOS11以上被废弃了,改用了UIScrollView 一个新的属性进行代替。

@available(iOS 11.0, *)
open var contentInsetAdjustmentBehavior: UIScrollViewContentInsetAdjustmentBehavior

虽然有替代的方案可以解决,但是我们这个例子当中并没有用到 UIScrollView。

我们假如继续大胆的猜测,会不会我们使用 UIStackView 的影响导致的呢。

我们为了验证这个猜想,立马去掉了我们使用 UIStackView 的布局,使用设置 Frame的方式设置我们里面的子试图。

2017-12-20 15_47_06

我们换成常规的使用 Frame 进行布局的时候,果然发现表现正常了。

到目前位置,暂没有找到因为 UISatckView 里面那个属性在 iOS11废弃了,导致这个问题的出现。

现在的解决办法有两个:

  • 使用手动计算的方式布局子试图
  • 使用设置约束设置子试图
  • 继续使用 UIStackView 但是布局在 y >= 20

在开发的过程中,直接布局在 y<20上面。并且使用 UIStackView 布局应该少之又少。

这虽然是一个问题的存在,但是不影响大家平时开发。

如果那个大神知道这个问题什么原因导致并知道解决办法的话,可以联系我帮助修正。