iOS11/iPhoneX相关适配问题

相信大家已经被iPhoneX的刘海洗脑了,除了吐槽,留给我们的还有比较麻烦的适配工作。下面针对在整理过程中发现的适配注意点进行简单分享下。

适配:
1.iPhone X 尺寸
2.iPhone X 上下显示黑条问题
3.导航栏的适配
4.iOS11新增版本判断API
5.UITableView相关适配
6.安全区域的问题
7.上传版本提示警告的问题
8.iOS 11 新增的隐私设置

一. iPhone X 尺寸

开发尺寸是375 * 812 pt

尺寸

二. iPhone X 上下显示黑条问题

运行Xcode9.0的iPhoneX模拟器, APP在iPhoneX屏幕没填充满,上下有黑色区域, 未适配前:

未适配前

这是因为app之前未用LaunchScreen.Storyboard作为启动页面,可以使用LaunchScreen来当做入场页面,这样APP才会自动适配为iPhoneX的大小。我的项目中是用Assets中的LaunchImage, 这样就可以修改Assets中的LaunchImage,添加iPhoneX的Launch图(1125*2436), 记得勾选如下图所示。

添加iPhoneX的Launch图

这个时候看下效果图:

适配后

三. 导航栏的适配

3.1 导航栏新增了一种大标题样式

默认设置是不开启,所以不需要修改。

3.2 高度适配

iOS 11以前,导航栏的高度是64,其中状态栏statusBar的高度是20,底部tabbar的高度是49。
iOS 11之后,iPhoneX的导航栏的高度是88,其中状态栏的statusBar的高度变成了44, 底部的tabbar变成了83。

iPhoneX的底部增加了虚拟Home区,由于安全区域的原因默认tabBar的高度由49变为83,增高了34,所以自定义的底部TabBar也需要需改其适配方案。

先来考虑关于navi 在 iPhone X 上是88的问题.
目前没发现有iPhoneX的机型判断API,建议使用size来做代替判断。

// 导航条高度
#define UI_navBar_Height  ((UI_View_Height == 812) ? 88.0 : 64.0) 

如果要在 navi 上添加渐变的背景图, 则要控制 navi 的高

- (UIImageView *)alphaView {
    if (!_alphaView) {
        CGRect frame = self.navigationBar.frame;
        CGFloat h = UI_navBar_Height; // is 812 ? 88 : 64
        UIImageView *alphaView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, h)];
        alphaView.image = [UIImage imageNamed:@"bg_gradient"];
        [self.navigationBar.subviews.firstObject insertSubview: alphaView atIndex:0];
        _alphaView = alphaView;
    }
    return _alphaView;
}

自定义的底部TabBar也需要改其适配方案, 则考虑适配 iPhone X

// 底部tabbar高度
#define UI_tabBar_Height  ((UI_View_Height == 812) ? 83.0 : 49.0) 
tabbar

3.3 titleView支持autolayout

这要求titleView必须是能够自撑开的或实现了- intrinsicContentSize,

适配前

这里以UISearchBar为例, 我是外层添加了titleView容器. 高度控制着35的.

    // 设置titleView
    UIView *titleView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 35)];//allocate titleView
    [titleView setBackgroundColor:[UIColor clearColor]];
    // 搜索工具条
    UISearchBar *searchBar = [[UISearchBar alloc] init];
    searchBar.placeholder = @"|搜索会员";
    searchBar.frame = CGRectMake(0, 0, titleView.width, 30);
    searchBar.center = titleView.center;
    searchBar.delegate = self;
    [titleView addSubview:searchBar];

    [self.navigationItem.titleView sizeToFit];
    self.navigationItem.titleView = titleView;

修改后, 发现UISearchBar圆角变形了,

UISearchBar圆角变形

这个时候我们可以添加设置圆角的, 效果如下:

searchBar.layer.cornerRadius = 10;
searchBar.layer.masksToBounds = YES;
适配后
  • 如果是自定义titleview, 只需要在你自定义的titleview对应的 View中实现- intrinsicContentSize方法;
- (CGSize)intrinsicContentSize {
    return UILayoutFittingExpandedSize;
}
  • 如果你的项目是自定义的navigationBar,那么在iOS11上运行就可能出现布局错乱,解决办法是重写UINavigationBar的 layoutSubviews方法,调整布局,代码如下:
- (void)layoutSubviews {
    [super layoutSubviews];
    
    //注意导航栏及状态栏高度适配
    self.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), naviBarHeight);
    for (UIView *view in self.subviews) {
        if([NSStringFromClass([view class]) containsString:@"Background"]) {
            view.frame = self.bounds;
        }
        else if ([NSStringFromClass([view class]) containsString:@"ContentView"]) {
            CGRect frame = view.frame;
            frame.origin.y = statusBarHeight;
            frame.size.height = self.bounds.size.height - frame.origin.y;
            view.frame = frame;
        }
    }
}

四. iOS11新增版本判断API

iOS11版本现在有了简单的API,OC也开始支持swfit的@available语法,就可以不用再手写判断iOS版本了。

if (@available(iOS 11.0, *)) {
  // 版本适配
}
// 或者
#ifdef __IPHONE_11_0   
#endif

五. UITableView相关适配

5.1 tableview的组头和组尾高度问题

iOS11开始UITableView开启了自动估算行高,estimatedRowHeight estimatedSectionHeaderHeight estimatedSectionFooterHeight三个高度估算属性由默认的0变成了UITableViewAutomaticDimension,把这三属性设置成0.01即可.

解决iOS11刷新tableview会出现漂移的现象, 添加以下代码关闭估算行高:

self.tableView.estimatedRowHeight = 0.01;
self.tableView.estimatedSectionHeaderHeight = 0.01;
self.tableView.estimatedSectionFooterHeight = 0.01;

heightForHeaderInSectionviewForHeaderInSection应该一起使用,不然tableView顶部滑动的时候会有空白。

heightForFooterInSectionviewForFooterInSection也应该一起使用, 如果仅仅 设置高度, 则tableView底部View根本没有展现。

5.2 Header/Footer返回size不能再为负值

在适配过程中发现UITableView会在Header/Footer返回size为负值的情况下会(之前遗漏的bug)崩溃,这块建议都修改为0.01,而iOS11之前的版本不会。

六.安全区域的问题

  • iOS 11之前, automaticallyAdjustsScrollViewInsets经常被设置成NO,由开发者去控制处理留白和坐标问题, 但是11+automaticallyAdjustsScrollViewInsets = NO这句代码失效。
  • iOS 11后,把这个automaticallyAdjustsScrollViewInsets废弃,新增了contentInsetAdjustmentBehavior,这个属性是个枚举类型值,我们只需要把其设置成never就行了

解决tableView偏移88的问题, 我们可以对对 tableView 进行如下设置:

if (@available(iOS 11.0, *)) {
    self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
} else {
    self.automaticallyAdjustsScrollViewInsets = NO;
}

七.Marketing Icon上传版本提示警告的问题

更新适配版本时 iPhone X 的启动图适配加上了, 千万别忘了也要传 Icon. 否则就会有上传版本时会有提示警告滴~

9月份上传的时候, 没有1024*1024的营销图标只是有警告, 现在上传的时候也是有警告的, 只不过现在提交审核的时候直接不能提交审核!


今天折腾一天,无论怎么更换这张图片(1024x1024的 png图)都不行, 最后换了一种上传方式Archive在线打包就好了,很尴尬~

八.iOS 11 新增的隐私设置

今天调试项目时有一个生成长图并保存到本地的功能,一点击保存相册就发现闪退了。发现 Xcode 报以下错误:

This app has crashed because it attempted to access privacy-sensitive data without a usage description.  The app's Info.plist must contain an NSPhotoLibraryAddUsageDescription key with a string value explaining to the user how the app uses this data.

问题跟 iOS 10 保存图片、调用相机一样, Info.plist 里面要涉及隐私数据时要添加提示语。
打开 Info.plist,点击 + 号,在 Key 中输入:Privacy - Photo Library Additions Usage Description,Type 选择 String,Value 中输入你的提示语。

这是 iOS 11 新出的一条隐私规则,说明如下:
iOS11下,苹果对相册的权限key做了调整,原来NSPhotoLibraryUsageDescription,在iOS11之后,改成了NSPhotoLibraryAddUsageDescription

iOS 11 新增的隐私设置
iOS 11 中新加的还有一个跟 NFC 设备有关 NFCReaderUsageDescription,不过暂时没接触到。

目前在iOS11/iPhoneX遇到这么多坑,以后遇到会继续分享的。

推荐一篇博客技术文, 有些内容我也是从这大神里学滴: http://fighting300.com/2017/09/14/iOS11-UI-adjust/

推荐阅读更多精彩内容