升級(jí)iOS10以后刁俭,遇到了很多新的的問題橄仍。經(jīng)過一段時(shí)間的適配,暴露的問題基本都已經(jīng)解決。這里把這些問題作一個(gè)統(tǒng)一的匯總侮繁,方便其他同學(xué)再遇到類似的問題時(shí)虑粥,進(jìn)行查閱。
這些問題宪哩,大致分為下面幾類:
一娩贷、權(quán)限crash閃退
iOS 10 開始對(duì)隱私權(quán)限更加嚴(yán)格,如果你不設(shè)置就會(huì)直接崩潰锁孟,現(xiàn)在很多遇到崩潰問題了彬祖,一般解決辦法都是在info.plist文件添加對(duì)應(yīng)的Key-Value就可以了。如下圖:
特別注意:value值不能為空品抽,否則AppStore提交會(huì)審核被拒储笑。
二、系統(tǒng)版本方法判斷失效
由于iOS系統(tǒng)已經(jīng)升級(jí)到iOS10圆恤,版本號(hào)由1位數(shù)變成了2位數(shù)突倍,在之前處理版本號(hào)相關(guān)的代碼需要重新檢查確認(rèn)沒有使用錯(cuò)誤,F(xiàn)irefly iOS組便發(fā)現(xiàn)此前使用的版本號(hào)判斷方法上存在缺陷盆昙。
項(xiàng)目組在此之前通過使用compare來(lái)對(duì)iOS系統(tǒng)的版本進(jìn)行比較赘方,具體代碼如下:
[[[UIDevicecurrentDevice] systemVersion] compare:@"9.0"] != NSOrderedAscending;
上述的代碼的意圖是判斷當(dāng)前iOS系統(tǒng)與9.0的關(guān)系,本來(lái)是要將字符串轉(zhuǎn)化成數(shù)字之后與9.0進(jìn)行比較弱左,然后得出結(jié)果。但在compare時(shí)存在缺陷炕淮,直接使用compare函數(shù)在比較時(shí)是將兩者當(dāng)成字符串進(jìn)行字典比較拆火,并非按預(yù)想根據(jù)數(shù)值比較。在iOS10版本之前涂圆,這行代碼返回的結(jié)果是對(duì)的们镜,因?yàn)閿?shù)字1-9在字典中的順序與數(shù)字順序一致,所以并未出錯(cuò)润歉。但當(dāng)iOS升級(jí)到10后模狭,版本獲取返回的”10.0”與”9.0”比較時(shí),會(huì)按字符串進(jìn)行字典比較踩衩,進(jìn)而先將”1”與”9”比較嚼鹉,結(jié)果發(fā)現(xiàn)”1”在”9”前面,從而認(rèn)為”10.0”小于”9.0”驱富,得出錯(cuò)誤結(jié)果锚赤,導(dǎo)致許多依賴版本的方法運(yùn)行出錯(cuò)。該方法有點(diǎn)類似于當(dāng)年的千年蟲褐鸥,缺陷會(huì)在某個(gè)時(shí)間才會(huì)暴露出來(lái)线脚,iOS升級(jí)到10便觸發(fā)這個(gè)bug的原因。版本判斷正確的方法是使用帶options的compare函數(shù),如下所示:
[[[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以后要采用更加嚴(yán)謹(jǐn)?shù)呐袛喾椒ǎ?/li>
#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 )
三浑侥、控制臺(tái)多余l(xiāng)og
XCode8新建一個(gè)工程姊舵,運(yùn)行。會(huì)發(fā)現(xiàn)控制臺(tái)輸出很多系統(tǒng)級(jí)別的log寓落,如果不想看到這些log括丁,解決辦法是設(shè)置OS_ACTIVITY_MODE : disable。
具體的途徑是:【product】-【scheme】-【Edit Scheme】-【Run】-【Argument】-【Environment Variable】添加keyValue【OS_ACTIVITY_MODE disable】可以停止輸出打印此日志零如。
四躏将、IDFA獲取失敗
首先關(guān)于IDFA的說(shuō)明文檔,有這么一句話:
Important
In iOS 10.0 and later, the value of advertisingIdentifier is all zeroes when the user has limited ad tracking.
ios10更新之后一旦開啟了 設(shè)置->隱私->廣告->限制廣告跟蹤之后 獲取到的idfa將會(huì)是一串00000 考蕾,而且每次開啟在關(guān)閉之后 相應(yīng)的idfa也會(huì)重新生成祸憋,相當(dāng)于還原了一次廣告標(biāo)識(shí)符。
針對(duì)這種修改肖卧,目前Firefly_iOS采用的解決方案是:
設(shè)備標(biāo)識(shí)首先采用IDFA蚯窥,獲取時(shí)增加判斷[[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled]
,如果獲取不到塞帐,就返回vender ID拦赠。
同時(shí),新增一個(gè)用戶設(shè)備指紋接口葵姥,專門標(biāo)識(shí)用戶的使用設(shè)備是否發(fā)生變化荷鼠。采用的方案是verder id + keychain。第一次將verder id存入keychain榔幸,之后都從keychain獲取允乐。
相關(guān)代碼實(shí)現(xiàn):
+ (NSString *)deviceIdentifier
{
static NSString *_identify = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (_identify == nil)
{
// iOS10以后IDFA可能會(huì)由于設(shè)置獲取不到
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;
}
五、模擬器環(huán)境削咆,RSA公鑰獲取不到牍疏,導(dǎo)致crash
具體的原因和keychain的權(quán)限問題有關(guān),將工程配置里的keychain開關(guān)打開即可拨齐。
六鳞陨、推送修改
首先,工程設(shè)置的開關(guān)一定要記得打開:
具體的使用規(guī)則瞻惋,先簡(jiǎn)單記錄如下厦滤,后續(xù)會(huì)繼續(xù)完善:
iOS 9 以前的通知
- 1.在調(diào)用方法時(shí),有些方法讓人很難區(qū)分歼狼,容易寫錯(cuò)方法馁害,這讓開發(fā)者有時(shí)候很苦惱。
- 2.應(yīng)用在運(yùn)行時(shí)和非運(yùn)行時(shí)捕獲通知的路徑還不一致蹂匹。
- 3.應(yīng)用在前臺(tái)時(shí)碘菜,是無(wú)法直接顯示遠(yuǎn)程通知,還需要進(jìn)一步處理。
- 4.已經(jīng)發(fā)出的通知是不能更新的忍啸,內(nèi)容發(fā)出時(shí)是不能改變的仰坦,并且只有簡(jiǎn)單文本展示方式,擴(kuò)展性根本不是很好计雌。
iOS 10 開始的通知
- 1.所有相關(guān)通知被統(tǒng)一到了UserNotifications.framework框架中悄晃。
- 2.增加了撤銷、更新凿滤、中途還可以修改通知的內(nèi)容妈橄。
- 3.通知不在是簡(jiǎn)單的文本了,可以加入視頻翁脆、圖片眷蚓,自定義通知的展示等等。
- 4.iOS 10相對(duì)之前的通知來(lái)說(shuō)更加好用易于管理反番,并且進(jìn)行了大規(guī)模優(yōu)化沙热,對(duì)于開發(fā)者來(lái)說(shuō)是一件好事。
- 5.iOS 10開始對(duì)于權(quán)限問題進(jìn)行了優(yōu)化罢缸,申請(qǐng)權(quán)限就比較簡(jiǎn)單了(本地與遠(yuǎn)程通知集成在一個(gè)方法中)篙贸。
七、ATS問題
- 1.在iOS 9的時(shí)候,默認(rèn)非HTTS的網(wǎng)絡(luò)是被禁止的,我們可以在info.plist文件中添加NSAppTransportSecurity字典,將NSAllowsArbitraryLoads設(shè)置為YES來(lái)禁用ATS;
- 2.從2017年1月1日起,所有新提交的 app 默認(rèn)不允許使用NSAllowsArbitraryLoads來(lái)繞過ATS的限制,默認(rèn)情況下你的 app 可以訪問加密足夠強(qiáng)的(TLS V1.2以上)HTTPS內(nèi)容;
- 3.可以選擇使用NSExceptionDomains設(shè)置白名單的方式對(duì)特定的域名開放HTTP內(nèi)容來(lái)通過審核,比如說(shuō)你的應(yīng)用集成了第三方的登錄分享SDK,可以通過這種方式來(lái)做枫疆。
下面以新浪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頁(yè)面加載,同時(shí)蘋果會(huì)用 ATS 來(lái)保護(hù)你的app。
九息楔、安全傳輸不再支持SSLv3,
建議盡快停用SHA1和3DES算法寝贡。
參考:
http://www.cnblogs.com/oc-bowen/p/5916630.html
http://www.2cto.com/kf/201609/547127.html