iOS10以及XCode8适配问题汇总

作者: kmplayer | 来源:发表于2016-11-03 10:15 被阅读665次

    升级iOS10以后,遇到了很多新的的问题。经过一段时间的适配,暴露的问题基本都已经解决。这里把这些问题作一个统一的汇总,方便其他同学再遇到类似的问题时,进行查阅。
    这些问题,大致分为下面几类:

    一、权限crash闪退

    iOS 10 开始对隐私权限更加严格,如果你不设置就会直接崩溃,现在很多遇到崩溃问题了,一般解决办法都是在info.plist文件添加对应的Key-Value就可以了。如下图:

    特别注意:value值不能为空,否则AppStore提交会审核被拒。

    二、系统版本方法判断失效

    由于iOS系统已经升级到iOS10,版本号由1位数变成了2位数,在之前处理版本号相关的代码需要重新检查确认没有使用错误,Firefly iOS组便发现此前使用的版本号判断方法上存在缺陷。
    项目组在此之前通过使用compare来对iOS系统的版本进行比较,具体代码如下:

    [[[UIDevicecurrentDevice] systemVersion] compare:@"9.0"] != NSOrderedAscending;
    

    上述的代码的意图是判断当前iOS系统与9.0的关系,本来是要将字符串转化成数字之后与9.0进行比较,然后得出结果。但在compare时存在缺陷,直接使用compare函数在比较时是将两者当成字符串进行字典比较,并非按预想根据数值比较。在iOS10版本之前,这行代码返回的结果是对的,因为数字1-9在字典中的顺序与数字顺序一致,所以并未出错。但当iOS升级到10后,版本获取返回的”10.0”与”9.0”比较时,会按字符串进行字典比较,进而先将”1”与”9”比较,结果发现”1”在”9”前面,从而认为”10.0”小于”9.0”,得出错误结果,导致许多依赖版本的方法运行出错。该方法有点类似于当年的千年虫,缺陷会在某个时间才会暴露出来,iOS升级到10便触发这个bug的原因。版本判断正确的方法是使用带options的compare函数,如下所示:

    [[[UIDevicecurrentDevice] systemVersion] compare:@"9.0" options:NSNumericSearch] != NSOrderedAscending;
    
    • 之前如果存在类似的代码:
    #define IOS10_OR_LATER ( [[[UIDevice currentDevice] systemVersion] compare:@"10.0"] != NSOrderedAscending )
    #define IOS9_OR_LATER ( [[[UIDevice currentDevice] systemVersion] compare:@"9.0" ] != NSOrderedAscending )
    
    • iOS10以后要采用更加严谨的判断方法:
    #define IOS10_OR_LATER  ( [[[UIDevice currentDevice] systemVersion] compare:@"10.0" options:NSNumericSearch] != NSOrderedAscending )
    #define IOS9_OR_LATER  ( [[[UIDevice currentDevice] systemVersion] compare:@"9.0" options:NSNumericSearch] != NSOrderedAscending )
    #define IOS8_OR_LATER  ( [[[UIDevice currentDevice] systemVersion] compare:@"8.0" options:NSNumericSearch] != NSOrderedAscending )
    #define IOS7_OR_LATER  ( [[[UIDevice currentDevice] systemVersion] compare:@"7.0" options:NSNumericSearch] != NSOrderedAscending )
    #define IOS6_OR_LATER  ( [[[UIDevice currentDevice] systemVersion] compare:@"6.0" options:NSNumericSearch] != NSOrderedAscending )
    #define IOS5_OR_LATER  ( [[[UIDevice currentDevice] systemVersion] compare:@"5.0" options:NSNumericSearch] != NSOrderedAscending )
    #define IOS4_OR_LATER  ( [[[UIDevice currentDevice] systemVersion] compare:@"4.0" options:NSNumericSearch] != NSOrderedAscending )
    #define IOS3_OR_LATER  ( [[[UIDevice currentDevice] systemVersion] compare:@"3.0" options:NSNumericSearch] != NSOrderedAscending )
    
    三、控制台多余log

    XCode8新建一个工程,运行。会发现控制台输出很多系统级别的log,如果不想看到这些log,解决办法是设置OS_ACTIVITY_MODE : disable。
    具体的途径是:【product】-【scheme】-【Edit Scheme】-【Run】-【Argument】-【Environment Variable】添加keyValue【OS_ACTIVITY_MODE disable】可以停止输出打印此日志。

    四、IDFA获取失败

    首先关于IDFA的说明文档,有这么一句话:

    Important
    In iOS 10.0 and later, the value of advertisingIdentifier is all zeroes when the user has limited ad tracking.

    ios10更新之后一旦开启了 设置->隐私->广告->限制广告跟踪之后 获取到的idfa将会是一串00000 ,而且每次开启在关闭之后 相应的idfa也会重新生成,相当于还原了一次广告标识符。
    针对这种修改,目前Firefly_iOS采用的解决方案是:
    设备标识首先采用IDFA,获取时增加判断[[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled],如果获取不到,就返回vender ID。
    同时,新增一个用户设备指纹接口,专门标识用户的使用设备是否发生变化。采用的方案是verder id + keychain。第一次将verder id存入keychain,之后都从keychain获取。
    相关代码实现:

    + (NSString *)deviceIdentifier
    {
        static NSString *_identify = nil;
        static  dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            if (_identify == nil)
            {
                // iOS10以后IDFA可能会由于设置获取不到
                if ([[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled])
                {
                    _identify = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
                }
                else
                {
                    _identify = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
                }
            }
        });
        
        return _identify;
    }
    
    + (NSString *)verifyCode
    {
        static NSString *_identify = nil;
        static  dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            if (_identify == nil)
            {
                _identify = [FireflyKeychain passwordForService:kFireflyAppIdentifyService
                                                       username:kFireflyAppIdentifyUser];
                if (_identify == nil)
                {
                    _identify = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
                    [FireflyKeychain setPassword:_identify
                                      forService:kFireflyAppIdentifyService
                                        username:kFireflyAppIdentifyUser];
                }
            }
        });
        
        return _identify;
    }
    
    五、模拟器环境,RSA公钥获取不到,导致crash

    具体的原因和keychain的权限问题有关,将工程配置里的keychain开关打开即可。

    六、推送修改

    首先,工程设置的开关一定要记得打开:

    具体的使用规则,先简单记录如下,后续会继续完善:
    iOS 9 以前的通知

    • 1.在调用方法时,有些方法让人很难区分,容易写错方法,这让开发者有时候很苦恼。
    • 2.应用在运行时和非运行时捕获通知的路径还不一致。
    • 3.应用在前台时,是无法直接显示远程通知,还需要进一步处理。
    • 4.已经发出的通知是不能更新的,内容发出时是不能改变的,并且只有简单文本展示方式,扩展性根本不是很好。

    iOS 10 开始的通知

    • 1.所有相关通知被统一到了UserNotifications.framework框架中。
    • 2.增加了撤销、更新、中途还可以修改通知的内容。
    • 3.通知不在是简单的文本了,可以加入视频、图片,自定义通知的展示等等。
    • 4.iOS 10相对之前的通知来说更加好用易于管理,并且进行了大规模优化,对于开发者来说是一件好事。
    • 5.iOS 10开始对于权限问题进行了优化,申请权限就比较简单了(本地与远程通知集成在一个方法中)。
    七、ATS问题
    • 1.在iOS 9的时候,默认非HTTS的网络是被禁止的,我们可以在info.plist文件中添加NSAppTransportSecurity字典,将NSAllowsArbitraryLoads设置为YES来禁用ATS;
    • 2.从2017年1月1日起,所有新提交的 app 默认不允许使用NSAllowsArbitraryLoads来绕过ATS的限制,默认情况下你的 app 可以访问加密足够强的(TLS V1.2以上)HTTPS内容;
    • 3.可以选择使用NSExceptionDomains设置白名单的方式对特定的域名开放HTTP内容来通过审核,比如说你的应用集成了第三方的登录分享SDK,可以通过这种方式来做。
      下面以新浪SDK作为示范:
    <key>NSAppTransportSecurity</key>
    <dict>
     <key>NSExceptionDomains</key>
     <dict>
      <key>sina.cn</key>
      <dict>
       <key>NSThirdPartyExceptionMinimumTLSVersion</key>
       <string>TLSv1.0</string>
       <key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
       <false>
       <key>NSIncludesSubdomains</key>
       <true>
      </true></false></dict>
      <key>weibo.cn</key>
      <dict>
       <key>NSThirdPartyExceptionMinimumTLSVersion</key>
       <string>TLSv1.0</string>
       <key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
       <false>
       <key>NSIncludesSubdomains</key>
       <true>
      </true></false></dict>
     </dict>
    </dict>
    
    八、NSAllowsArbitraryLoadsInWebContent键

    在iOS 10 中info.plist文件新加入了NSAllowsArbitraryLoadsInWebContent键,允许任意web页面加载,同时苹果会用 ATS 来保护你的app。

    九、安全传输不再支持SSLv3,

    建议尽快停用SHA1和3DES算法。

    参考:
    http://www.cnblogs.com/oc-bowen/p/5916630.html
    http://www.2cto.com/kf/201609/547127.html

    相关文章

      网友评论

        本文标题:iOS10以及XCode8适配问题汇总

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