swift3.0AFNetworkingXcode8.0 iOS10权限设置 新特性

iOS10以及XCode8适配问题汇总

2016-11-03  本文已影响665人  kmplayer

升级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 )
#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 以前的通知

iOS 10 开始的通知

七、ATS问题
<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

上一篇 下一篇

猜你喜欢

热点阅读