iOS 11适配及问题解决方案

苹果虐我千百遍,我待苹果如初恋。 横批:iOS开发苦。
iOS 11系统对于开发者来说,变化不算小,各种适配问题接踵而至。
本文主要介绍 UINavigationBar 层级结构变化,UIScrollView Layout变化,UISearchBar宽高变化,引起的问题的原理分析,着重提出解决方案,还有iPhone X的适配。附言介绍一下Xcode 9的小Tips。

问题一:

1、导航栏高度变化:

iOS 11添加了大标题,由系统属性prefersLargeTitles决定,NavigationBar高度如下图1、2:

iOS 11适配及问题解决方案_第1张图片
图1 iPhone X之前机型.png
iOS 11适配及问题解决方案_第2张图片
图2 iPhone X.png

总结来说:如果都用的系统的NavigationBar,全部无需适配高度。但是(忽略LargeTitle部分)如果自定义的NavigationBar,iPhone X之前机型正常height == 64,对于程序中很多写死的64,简直是福音,无需更改,但对于iPhone X的高度则变成height == 88,不得不适配。可能需要的两个宏定义:

#define kStatusBarHeight      CGRectGetHeight([[UIApplication sharedApplication] statusBarFrame])
#define kNavigationBarHeight  CGRectGetHeight([[UIApplication sharedApplication] statusBarFrame]) + CGRectGetHeight(self.navigationController.navigationBar.frame)

2、导航栏图层变化

这个实在是搞大事啊。

在iOS11之后,苹果添加了新的类来管理,navigationBar会添加在_UIButtonBarStackView上面,而_UIButtonBarStackView则添加在_UINavigationBarContentView上面;如果没有给titleView赋值,则titleView会直接添加在_UINavigationBarContentView上面,如果赋值给了titleView,则会新生成_UITAMICAdaptorView,把titleView添加在这个类上面,这个类会添加在_UINavigationBarContentView上面,如下图3、4:


iOS 11适配及问题解决方案_第3张图片
图3.png
iOS 11适配及问题解决方案_第4张图片
图4.png

3、导航栏边距变化

在iOS 11对导航栏里面的UIBarButtonItem的边距也做了调整:

在iOS 11之前,我们可以设置一个width为负值,类型为UIBarButtonSystemItemFixedSpace的navigationBarButton,间按钮挤到屏幕边缘,如下图5:

图5.png

但是iOS 11,这招失效啦,原因就在于NavigationBar图层发生了变化,引起了如下图6的问题:

图6.png
解决方案:
(1)最简单粗暴的方式,在每个需要设置item的VC中,设置button的setContentEdgeInsets:
(2)在viewWillAppear里面,将_UIButtonBarStackView取出来,直接通过layoutMargins设置偏移量。如下:
//设置leftBarButtonItem
for (UIView *view in self.navigationController.navigationBar.subviews[2].subviews) {
        if ([view isKindOfClass:UIStackView.class]) {
            view.layoutMargins = UIEdgeInsetsMake(0, -15, 0, 0);
        }
}
(3)同上述方法2的原理,通过动态运行时,hock住setLeftBarButtonItem:setRightBarButtonItem:系统方法,创建自定义的View,在View的layoutSubviews方法中,找到UIStackView,通过NSLayoutConstraint调整该视图的布局,达到目的,但是也需要在viewWillAppear里面重新创建,不然当push到下一级页面时,再返回,位置会恢复。
转载大神的Demo地址如下:

https://github.com/spicyShrimp/iOS-11-UINavigationItem-SXFixSpace

(4)完全舍弃系统的Navi,自定义Navi,个人不建议使用,不仅要适配 安全区域,如果哪天苹果Daddy心血来潮,又改啦,呵呵。

问题二:滚动视图的变化

1、iOS11弃用了automaticallyAdjustsScrollViewInsets属性

导致的现象:UITableView列表出现错位;页面切换过程中出现抖动问题。
解决办法:

//在基类VC中
if (@available(iOS 11.0, *)) {
      [UIScrollView appearance].contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}

2、UITableView默认使用Self-Sizing

iOS 11中如果不实现-tableView: viewForFooterInSection: 和 -tableView: viewForHeaderInSection:,那么-tableView: heightForHeaderInSection:和- tableView: heightForFooterInSection:不会被调用。
这是因为 estimatedRowHeight、estimatedSectionHeaderHeight、 estimatedSectionFooterHeight 三个高度估算属性由默认的0变成了UITableViewAutomaticDimension,导致高度计算不对。
解决方法:实现对应方法或把预估的三个属性值设为0。
目前项目中由此引起的问题不大。

问题三:UISearchBar高度适配

1、SearchBar在Navi的titleView中,高度发生变化

现象:

图 7.png

解决办法:自定义View,重写系统方法,赋值给titleview。如下:

- (CGSize)intrinsicContentSize {
    if (@available(iOS 11.0, *)) {
        return UILayoutFittingCompressedSize;
    }
    return CGSizeZero;
}

iPhone X适配:

1、启动图和AppIcon
iOS 11适配及问题解决方案_第5张图片
图 8.png

启动图规格尺寸:1125 * 2436 (357pt * 812pt @3x)
AppIcon尺寸:多了一个App Store的图标。

iOS 11适配及问题解决方案_第6张图片
图 9.png
2、刘海布局

大部分的系统控件,如NavigationBar、TabBar、表单等会自动适配iPhone X的屏幕,无需适配,但是如果自定义的话,就得手动适配啦,NavigationBar空出刘海位置,TabBar空出HomeBar位置,都位于安全区域以内。

3、横屏布局,尚未研究。

Xcode 9的小Tips:

1、导入图片问题

直接将图片拖入工程的粗暴方式已经不行啦, 会导致无法读取图片,可以通过“Add File To ....”,不习惯好吧。Xcode 9可以打开Assets,将图片资源直接拖进去,直观方便。

2、Assets中添加颜色

在Asset中,可以创建颜色了。右键选择New image set,填充RGBA值或十六进制值即可。使用中直接使用新的colorwithname,参数填入创建时的名字即可。使用时一定记得区分系统版本。

3、command键复原,直接跳转

可在Preferences --> Navigation --> Command-click on Code 中选择Jumps to Defintion即可。

参考

你可能需要为你的 APP 适配 iOS 11
App界面适配iOS11
iOS11 导航栏按钮位置问题的解决

你可能感兴趣的:(iOS 11适配及问题解决方案)