美文网首页
iOS11, Xcode9 and iphone X适配

iOS11, Xcode9 and iphone X适配

作者: 花了个缺 | 来源:发表于2017-12-11 16:15 被阅读234次

    前言

    最近公司的很多流量产品需要适配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的高度,如果项目里隐藏了导航栏加了自定义按钮之类的,这里需要注意适配一下。

    968977-89a88f618da51832.png
    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

     <!-- 位置 -->
    <key>NSLocationUsageDescription</key>
    <string>获取地理位置,精准推送服务</string>
    <!-- 在使用期间访问位置 -->
    <key>NSLocationWhenInUseUsageDescription</key>
    <string>获取地理位置,精准推送服务</string>
    <!-- 始终访问位置 -->
    <key>NSLocationAlwaysUsageDescription</key>
    <string>App需要您的同意,才能始终访问位置</string>
    <!-- iOS 11访问位置 -->
    <key>NSLocationAlwaysAndWhenInUseUsageDeion</key>
    <string>App需要您的同意,才能始终访问位置</string>
    
    1. 使用第三方网络监测库报错


      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来继承。


      CA99B4BE-B322-453E-951E-A0B5B32E4530.png

    总结

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

    相关文章

      网友评论

          本文标题:iOS11, Xcode9 and iphone X适配

          本文链接:https://www.haomeiwen.com/subject/bazeixtx.html