公司的应用是居于iOS8上以上的,页面显示在iOS8上〜iOS10都没有问题,但是,iOS11beta版显示出现各种问题,真是顾客虐你千百遍,你待顾客如初恋,苹果搞事,我们也只能暗暗的承受.😜
搞事一:导航栏
1.导航栏高度变化
导航栏在iOS10之前都是默认的64P,但是,到了iOS10就不单单是64P了,可以看一下系统的信息应用程序,在iOS11添加了大标题,效果如下图1:
图1.png
的导航栏的结构,看图2,3,4:
图2.png
图3.png
图4.png
在上面三幅图可以知道,在iOS11导航栏多了一个LargeTitleView,专门显示大字标题用的,整个导航栏的高度达到了96P,这不包括状态栏的高度,也就是说,整个应用程序顶部高度达到了116p,其中statusbar = 20,title = 44,largetitle = 52,不过默认是64p;当然,iPhoneX的高度会更高点,如果不显示大字标题,顶部的高度也达到了88,statusbar = 44,title = 44,如果显示大字标题,则高度变成了140,statusbar = 44,title = 44,largetitle = 52,也就是说,iPhoneX的刘海高度为24p,大字标题如下图:
iPhoneX之前的机型巴纽
iPhoneX.png
2.导航栏的图层变化
iOS11之前导航栏的标题是添加在UINavigationItemView上面,而navigationBarButton则直接添加在的导航栏上面;如果设置了titleview的,则titleview的也是直接添加在的导航栏上面,如图5:
图5.png
在iOS11之后,苹果添加了新的类来管理,的导航栏会添加在_UIButtonBarStackView上面,而_UIButtonBarStackView则添加在_UINavigationBarContentView上面;如果没有给titleview的赋值,则titleview的会直接添加在_UINavigationBarContentView上面,如果赋值给了titleview的,则会新生成_UITAMICAdaptorView,把titleview的添加在这个类上面,这个类会添加在_UINavigationBarContentView上面,如下图6,7:
图6.png
图7.png
3.导航栏的边距变化
在iOS11对导航栏里面的物品的边距也做了调整:
(1)如果只是设置了titleview的,没有设置barbutton,把titleview的的宽度设置为屏幕宽度,则titleview的距离屏幕的边距,iOS11之前,在iPhone6p上是20P,在iPhone6p之前是16P; iOS11之后,在iPhone6p上是12P,在iPhone6p之前是8P。
(2)如果只是设置了barbutton,没有设置titleview的,则在iOS11里,barButton距离屏幕的边距是20P和16P;在iOS11之前,barButton距离屏幕的边距也是20P和16P。
(3)如果同时设置了titleview的和barButton,则在iOS11之前,titleview的和barbutton之间的间距是6P,在iOS11上titleview的和barbutton之间无间距,如下图8,9:
图8.png
图9.png
4.App需要实现导航栏左右按钮边距为0
在iOS11之前,可以设置一个宽度为负的navigationBarButton,将按钮挤到边缘,变相实现0边距的导航栏按钮,但是,这招在iOS11失效了,原因在于_UIButtonBarStackView,这个iOS9之后出来的,用来相对布局的组件,限制了子视图的布局。那怎么搞呢?
想要的方法有几个:
(1)在viewWillAppear里面,将_UIButtonBarStackView取出来,直接设置它的x坐标。
(2)设置titleView,然后将按钮添加在titleView上面,根据不同的边距做偏移。
方法一:
遇到的问题,在viewDidLoad中,viewWillAppear中,viewWillLayoutSubviews,viewDidLayoutSubviews里面都取不到_UIButtonBarStackView,只有在viewDidAppear里才能取到值,这样就会在页面显示了之后才开始移动navigationBarButton,显然这样体验不好,所以,暂时通过掉。
方法二:
。这个做法完全可以做到0边距,但是,问题来了,就是点击区域的问题因为左右navigationBarButton的点击区域是超出父视图的,所以,点击不到这好办,重写titleview的的则hitTest方法就好。嘿嘿嘿,问题没有那么简单。之前在iOS11的图层结构就解释过,titleview的会被添加在_UITAMICAdaptorView上面,而重点是,这个视图也有边距,所以,单单重写titleview的的则hitTest方法还不够,那怎么解决呢?我的办法就是写一个视图的类别,钩所有视图的则hitTest方法,在里面判断是否是iOS11以上,是否是_UITAMICAdaptorView类,如果都满足条件,则可以搞事了.😜演示
搞事二:列表的变化
1.automaticallyAdjustsScrollViewInsets
在iOS11之前,如果想要滚动视图不偏移64P,则需设置automaticallyAdjustsScrollViewInsets = NO,但是这个属性在iOS11直接被遗弃了😳:
@property(nonatomic,assign) BOOL automaticallyAdjustsScrollViewInsetsAPI_DEPRECATED_WITH_REPLACEMENT("Use UIScrollView's contentInsetAdjustmentBehavior instead", ios(7.0,11.0),tvos(7.0,11.0));
所以,看一下contentInsetAdjustmentBehavior是何方神圣:
typedef NS_ENUM(NSInteger, UIScrollViewContentInsetAdjustmentBehavior) {UIScrollViewContentInsetAdjustmentAutomatic, // Similar to .scrollableAxes, but will also adjust the top & bottom contentInset when the scroll view is owned by a view controller with automaticallyAdjustsScrollViewContentInset = YES inside a navigation controller, regardless of whether the scroll view is scrollableUIScrollViewContentInsetAdjustmentScrollableAxes, // Edges for scrollable axes are adjusted (i.e., contentSize.width/height > frame.size.width/height or alwaysBounceHorizontal/Vertical = YES)UIScrollViewContentInsetAdjustmentNever, // contentInset is not adjustedUIScrollViewContentInsetAdjustmentAlways, // contentInset is always adjusted by the scroll view's safeAreaInsets} API_AVAILABLE(ios(11.0),tvos(11.0));/* Configure the behavior of adjustedContentInset.Default is UIScrollViewContentInsetAdjustmentAutomatic.*/@property(nonatomic) UIScrollViewContentInsetAdjustmentBehavior contentInsetAdjustmentBehavior API_AVAILABLE(ios(11.0),tvos(11.0));
看起来这和iOS11搞的safeArea有关,这个先放一遍,看看怎么适配:
#define adjustsScrollViewInsets_NO(scrollView,vc)\do { \_Pragma("clang diagnostic push") \_Pragma("clang diagnostic ignored \"-Warc-performSelector-leaks\"") \if ([UIScrollView instancesRespondToSelector:NSSelectorFromString(@"setContentInsetAdjustmentBehavior:")]) {\[scrollView performSelector:NSSelectorFromString(@"setContentInsetAdjustmentBehavior:") withObject:@(2)];\} else {\vc.automaticallyAdjustsScrollViewInsets = NO;\}\_Pragma("clang diagnostic pop") \} while (0)
上面是公司里面一个大神写的,这样就可以在Xcode8上面跑了。
2.tableView默认使用自调整大小
这个配合estimatedRowHeight,estimatedSectionFooterHeight,estimatedSectionHeaderHeight使用,可以预估高度。之前,设置高度为0时,需要设置高度= 0.1,才会起作用,如果直接设置为0,则会使用默认高度,由于自动使用预估高度,所以,忽略了设置的高度,使原来的高度增大了。只要把这几个属性设置为0就可以解决。
搞事三:iPhoneX底部的TabBar的高度改变
iPhoneX不止多了刘海,底部还有一个半角的矩形,使得的TabBar多出来了34P的高度,不过不管导航栏和的TabBar一般系统都会自动适配safeArea。
iPhoneX tabbar.png
总结:
iOS11系统改变还是比较大的,某些地方需要注意适配,不然会出现很奇怪的现象。暂时,在iOS11遇到这么多坑,以后遇到会继续分享的。