iOS11, Xcode9 and iphone X适配

前言

最近公司的很多流量产品需要适配iOS 11 和iPhone X,由于公司的iPhone X到的比较晚,拖了好久才对这些流量产品进行更新。

问题

  1. 首先一个很明显的适配问题,就是打开app的时候没有全屏,这时候要加入一张对应尺寸的启动图片就可以。
  • 竖屏尺寸:1125px × 2436px(375pt × 812pt @3x)
  • 横屏尺寸:2436px × 1125px(812pt × 375pt @3x)
  1. 跟启动屏有关的当然还有一个问题,那就是获取屏幕的大小:[[UIScreen mainScreen] bounds].size 加入上面的图片就可以了

导航栏

  1. navigationItem.titleView = 自定义view, 这时候这个自定义的view的大小就会出现问题,而且有点击时间也不会触发。首先,在自定义titleview 里重写 intrinsicContentSize 属性,代码如下

    @property(nonatomic, assign) CGSize intrinsicContentSize;
    

然后在 self.navigationItem.titleView = _titleView; 之前加入下面的代码:

_titleView.intrinsicContentSize = CGSizeMake(200, 40);

自定义的view还是要设置frame,不然不是iOS11还是可能出问题。

  1. 导航栏高度的变化

iOS11之前导航栏默认高度为64pt(这里高度指statusBar + NavigationBar),iOS11之后如果设置了prefersLargeTitles = YES则为96pt,默认情况下还是64pt,但在iPhoneX上由于刘海的出现statusBar由以前的20pt变成了44pt,所以iPhoneX上高度变为88pt,由于刘海多出了24pt的高度,如果项目里隐藏了导航栏加了自定义按钮之类的,这里需要注意适配一下。

iOS11, Xcode9 and iphone X适配_第1张图片
968977-89a88f618da51832.png

iOS11, Xcode9 and iphone X适配_第2张图片
968977-b19a09df0a51bf50.png

viewSafeAreaInsetsDidChange方法里面打印NSLog(@"%@",NSStringFromUIEdgeInsets(self.view.safeAreaInsets));即可知道安全区域的边界

  1. 在iOS7之后,我们在设置UINavigationItemleftBarButtonItem,rightBarButtonItem的时候都会造成位置的偏移,我们经常习惯使用下面这个方法来调整下间距

    +(UIBarButtonItem *)fixedSpaceWithWidth:(CGFloat)width {`
     UIBarButtonItem *fixedSpace = [[UIBarButtonItem         alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
     fixedSpace.width = width;
     return fixedSpace;
     }
    

但是在iOS11没有效果了,可以通过过改变按钮的 contentEdgeInsetsimageEdgeInsets的值成功改变了按钮的偏移问题,单独设置contentEdgeInsets也可达到一定的效果

底部tarbar

  1. iPhone x:Tabbar从49pt变为83pt,如果是自己定义的tabbar需要自己加上34的高度,否则会点不到对应tabbar。如果是隐藏的tabbar的话,比如底部放了一个banner广告的话,这时候也需要调整对应的高度,在xcode中调整了下如果隐藏tabbar,还要在底部放广告的话可以距离底部24pt,苹果tabbar多加了34,比点击距离多加了10pt,应该是让用户体验更加的好点,不然24的话感觉快点到底部触摸栏的样子。

UITableView and UICollectionView

  1. 在iOS 11上运行tableView向下偏移64px或者20px,因为iOS 11废弃了automaticallyAdjustsScrollViewInsets,而是给UIScrollView增加了contentInsetAdjustmentBehavior属性。避免这个坑的方法是要判断

       if (@available(iOS 11.0, *)) {
         _tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
       }else {
         self.automaticallyAdjustsScrollViewInsets = NO;
       }
    
  2. IOS11以后,Self-Sizing默认开启,包括Headers, footers。如果项目中没使用estimatedRowHeight属性,在IOS11下会有奇奇怪怪的现象,默认如果不去实现viewForHeaderInSection就不会调用heightForHeaderInSection,尾部试图一样,因为IOS11之前,estimatedRowHeight默认为0,Self-Sizing自动打开后,contentSizecontentOffset都可能发生改变。可以通过以下方式禁用:

     self.tableView.estimatedRowHeight = 0; 
     self.tableView.estimatedSectionHeaderHeight = 0; 
     self.tableView.estimatedSectionFooterHeight = 0;
    
  3. 列表/页面偏移,设置工程中的UITableView、UICollectionView、UIScrollView的contentInsetAdjustmentBehavior属性,如下:

       if (@available(iOS 11.0, *)){
         _tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
      }
    

总的来说所有继承与Scrollview 及其子类都需要设置 contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever ,每个设置很麻烦,没关系。由于UIView及其子类都遵循UIAppearance协议,我们可以进行全局配置:

// AppDelegate 进行全局设置
if (@available(iOS 11.0, *)){
    [[UIScrollView appearance]     setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever];
}
  1. 当你在tableView 里面嵌套collectionView 的时候有可能出现一下错误:

     Assertion failure in -[UICollectionViewData validateLayoutInRect:],              /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3694.4.18/UICollectionViewData.m:435
     2017-11-15 15:59:08.616969+0800 tbEmojiGuangchang[70423:3415148] invalid mode 'kCFRunLoopCommonModes' provided to CFRunLoopRunSpecific - break on _CFRunLoopError_RunCalledWithInvalidMode to debug. This message will only appear once per execution.
    

    libc++abi.dylib: terminate_handler unexpectedly threw an exception

只要在刷新collectionView之前调用[collectionView.collectionViewLayout invalidateLayout] 就行。

  -(NSInteger) numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
      [collectionView.collectionViewLayout invalidateLayout];
      return 1;
  }
  1. 相册权限
    iOS11之后:默认开启访问相册权限(读权限),无需用户授权,无需添加NSPhotoLibraryUsageDescription,适配iOS11之前的还是需要加的。 添加图片到相册(写权限),需要用户授权,需要添加 NSPhotoLibraryAddUsageDescription,相册的权限状态有以下四种状态:

     PHAuthorizationStatusNotDetermined = 0, // User has not yet made a choice with regards to this application
     PHAuthorizationStatusRestricted,        // This application is not authorized to access photo data.
                                        // The user cannot change this application’s status, possibly due to active restrictions
                                        //   such as parental controls being in place.
    PHAuthorizationStatusDenied,            // User has explicitly denied this application access to photos data.
    PHAuthorizationStatusAuthorized         // User has authorized this application to access photos data.
    

iOS11之前如果还没请求访问相册权限的话状态是:PHAuthorizationStatusNotDetermined ,用户如果点击不允许访问相册的话状态是:PHAuthorizationStatusDenied ,但是在iOS11就很奇葩,还没请求访问相册权限和用户如果点击不允许访问相册的状态都是PHAuthorizationStatusNotDetermined,导致不能判断是否是用户点击不允许的操作,也就没办法弹出那个引导用户去设置开启相册权限的窗口。我这边的做法是如果应用是有需要添加相片到相册的,要提前请求相册功能:

oc 代码:

[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
    
}];

swift 代码:

if #available(iOS 11.0, *) {
        let library: PHAuthorizationStatus = PHPhotoLibrary.authorizationStatus()
        if(library == PHAuthorizationStatus.notDetermined){
            PHPhotoLibrary.requestAuthorization { (status) in
            }
        }
 }
  1. 位置权限

在IOS11,原有的NSLocationAlwaysUsageDeion被降级为NSLocationWhenInUseUsageDeion。因此,在原来项目中使用requestAlwaysAuthorization获取定位权限,而未在plist文件中配置NSLocationAlwaysAndWhenInUseUsageDeion,系统框不会弹出。建议新旧key值都在plist里配置,反正我试下来是没有问题,唯一的区别是使用requestAlwaysAuthorization获取权限 IOS11系统弹框会把几种权限级别全部列出,供用户选择,显然更人性化了。快去更新你的info.plist

 
NSLocationUsageDescription
获取地理位置,精准推送服务

NSLocationWhenInUseUsageDescription
获取地理位置,精准推送服务

NSLocationAlwaysUsageDescription
App需要您的同意,才能始终访问位置

NSLocationAlwaysAndWhenInUseUsageDeion
App需要您的同意,才能始终访问位置
  1. 使用第三方网络监测库报错


    iOS11, Xcode9 and iphone X适配_第3张图片
    325120-0850ff880b326807.png

解决方式如下:替换成如下代码:

__Check_Compile_Time(sizeof(ICMPHeader) == 8);
__Check_Compile_Time(offsetof(ICMPHeader, type) == 0);
__Check_Compile_Time(offsetof(ICMPHeader, code) == 1);
__Check_Compile_Time(offsetof(ICMPHeader, checksum) == 2);
__Check_Compile_Time(offsetof(ICMPHeader, identifier) == 4);
__Check_Compile_Time(offsetof(ICMPHeader, sequenceNumber) == 6)

后续更新...

  1. 跳转appStore评论的链接更换了,很正常,因为iOS11之后appStore就大改版了,当然跳到里面的链接应该也是会有所变化的,之前iOS11的链接是这样的:

    http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=XXXXXXXX&pageNumber=0&sortOrdering=2&type=Purple+Software&mt=8"
    

iOS11之后需要改称以下这样,当然iOS11之前这个链接也是适用的:

itms-apps://itunes.apple.com/cn/app/idXXXXXX?mt=8&action=write-review
  1. UIToolBar 的坑,当你使用view集成UIToolBar的时候,这个时候使用xcode9运行的时候会发现一个非常坑的问题,就是在view的最顶层会多出一层UIToolBarContenVIew出来,到时你的整个view没办法点击,建议不要用UIToolbar来继承。


    iOS11, Xcode9 and iphone X适配_第4张图片
    CA99B4BE-B322-453E-951E-A0B5B32E4530.png

总结

以上是我在适配我的一些产品的时候碰到的一些问题,当然还有一些其他很小的细节有问题,只需要稍微调整就行,在这里就不提了,苹果每次更新一个大版本的时候都会出现各种各样的问题,很多东西也变得越来越复杂,后面有在项目中碰到问题会在继续更新~

你可能感兴趣的:(iOS11, Xcode9 and iphone X适配)