我为什么要说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 转换成 OCOC 工程运行
  3. 可以使用 Carthage 很方便的打包成 Framework 接入 CarthageCocoapods
  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 布局应该少之又少。

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

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