使用AutoLayout时,在iOS7和iOS8上两者会有很大的不同,iOS8苹果优化了很多。最近看了一篇bolg,是Reveal的工程师写的介绍使用Constraints以及transform变幻之后在iOS78上的异同。
先贴张图说明一下问题:

可以看到iOS7在使用了autolayout之后,进行transform变幻之后view并没有达到预期效果,而在iOS8和和纯frame布局的情况下是正常的。
autolayout使用的是Top和leading与灰色的view进行约束,而frame是通过setCenter来设置位置的。
这种错误的现象会发生在iOS7及以前的版本中,在iOS8之后得到了修复。
通过Reveal查看可以看到:

使用autolayout的view跟他的参照View相比只移动了(-10,-10),而且它的布局位置也发生了偏移(10,10),在iOS8下查看,会发现布局位置并没有移动,跟参照View完全一致

由此可以得到的结论就是,在iOS7和8上使用autolayout布局的view的center属性的位置发生了改变。
通过设置断点和重写setFrame和setCenter方法研究发现,在iOS7和8上setFrame方法都没有被UIKit调用到,而只有setCenter方法被调用。
“If the transform property is not the identity transform, the value of this property is undefined and therefore should be ignored.”
————UIView’s Class Reference
如果transform属性不是identity的,那么他的值就是不确定的而且应该被忽略。因此可以断定setFrame方法没有没调用,因而view的transform属性也就不是identity的,所以会出现问题。
至于具体的iOS7和8在NSISLayoutEngine里面做了什么改变,可以查看博客原文。
最后说一下结论:如果我们的app是使用iOS8或者以后的SDK编译链接的并且还要支持iOS7,并在没有identity的transform的view上使用了AutoLayout。那么就应该注意一下几点:
- 如果只使用旋转和缩放的
transform变换,那么就要使用CenterX/CenterY约束,来替代Top/Bottom/Left/Right/Trailing/Leading约束,因为如果transform的view是通过它的centre布局的话,那么结果就有可能是正确的。 - 将要变换的
view放到一个containerView里,然后用约束约束containerView好过直接约束变换的view。变换的view可以直接用代码布局,也可以用CentreX/CenterY约束。但是使用等宽等高与containerView建立约束将不会达到预期效果 - 不要使用
constraint来约束这些View,使用autosizingMask,然后设置这些View的translatesAutoresizingMaskIntoConstraints为YES。
PS:
最后算是做个广告吧,Reveal这个工具真的是很NB很好用,当你使用了之后就会爱不释手。它可以查看view的层级关系,动态的改变UI属性,在最近的版本还支持对autolayout的支持,可以查看constraints已经对他们进行修改,我们做iOS开发的更多的是做界面开发工作,那么有了这样一个神器在手,那么必然会达到事半功倍的效果,工欲善其事,必先利其器!
Reveal还能做更NB的事情就是当你手机越狱后,然后你就可以查看任何app的视图层级关系了。就说到这里了,至于接下来怎样大家自己脑补吧。
既然这个工具这么强大,我们还是支持一下作者吧,同为开发者,都知道这行挺不容易的还是支持下正版吧,好消息是Reveal对中国的开发者们有个特惠价格:RMB249就可以拿下了,购买地址,比半价还优惠,我在知道这个消息后第一时间拿下了它,因为之前的价格确实有点贵,对我来说还是有压力的。
————————————
