很可能你的應(yīng)用是與一個支持HTTPS傳輸數(shù)據(jù)的服務(wù)器交互,但是并沒有使用TLS 1.2或更高。在這種情況下渗勘,你定義一個“例外”(Exception)细疚,它指明應(yīng)該使用的最小的TLS的版本蔗彤。這比完全撤銷那個域名的App Transport Security要更好更安全。1.iOS9網(wǎng)絡(luò)適配_ATS:改用更安全的HTTPS
thatotherdomain.com
Info.plist 配置中的XML源碼如下所示:
為了強制增強數(shù)據(jù)訪問安全疯兼, iOS9 默認會把 所有的http請求 所有從NSURLConnection 然遏、 CFURL 、 NSURLSession發(fā)出的 HTTP 請求吧彪,都改為 HTTPS 請求:iOS9.x-SDK編譯時待侵,默認會讓所有從NSURLConnection 、 CFURL 姨裸、 NSURLSession發(fā)出的 HTTP 請求統(tǒng)一采用TLS 1.2 協(xié)議秧倾。因為 AFNetworking 現(xiàn)在的版本底層使用了 NSURLConnection ,眾多App將被影響(基于iOS8.x-SDK的App不受影響)傀缩。服務(wù)器因此需要更新那先,以解析相關(guān)數(shù)據(jù)。如不更新赡艰,可通過在 Info.plist 中聲明售淡,倒退回不安全的網(wǎng)絡(luò)請求。而這一做法慷垮,官方文檔稱為ATS揖闸,全稱為App Transport Security,是iOS9的一個新特性料身。
一個符合 ATS 要求的 HTTPS汤纸,應(yīng)該滿足如下條件:
Transport Layer Security協(xié)議版本要求TLS1.2以上
服務(wù)的Ciphers配置要求支持Forward Secrecy等
證書簽名算法符合ATS要求等
注:有童鞋反映:服務(wù)器已支持TLS 1.2 SSL ,但iOS9上還是不行芹血,還要進行本文提出的適配操作贮泞。
那是因為:要注意 App Transport Security 要求 TLS 1.2,而且它要求站點使用支持forward secrecy協(xié)議的密碼祟牲。證書也要求是符合ATS規(guī)格的隙畜,ATS只信任知名CA頒發(fā)的證書,小公司所使用的 self signed certificate说贝,還是會被ATS攔截议惰。。因此慎重檢查與你的應(yīng)用交互的服務(wù)器是不是符合ATS的要求非常重要乡恕。對此言询,建議使用下文中給出的NSExceptionDomains俯萎,并將你們公司的域名掛在下面。下文也會詳細描述該問題运杭。
官方文檔 App Transport Security Technote 對CA頒發(fā)的證書要求:Cocoa Keys
什么是SSL/TLS夫啊?跟HTTP和HTTPS有什么關(guān)系
什么是SSL/TLS? SSL你一定知道辆憔,在此不做贅述撇眯。主要說下什么是TLS,還有跟HTTP和HTTPS有什么關(guān)系虱咧。
TLS 是 SSL 新的別稱:
“TLS1.0”之于“SSL3.1”熊榛,猶“公元2015”之于“民國104”,“一千克”之于“一公斤”:稱呼不同腕巡,意思相同玄坦。
SSL 3.0版本之后的迭代版本被重新命名為TLS 1.0:TLS 1.0=SSL 3.1。所以我們平常也經(jīng)常見到 “SSL/TLS” 這種說法绘沉。
目前煎楣,應(yīng)用最廣泛的是TLS 1.0,接下來是SSL 3.0车伞。目前主流瀏覽器都已經(jīng)實現(xiàn)了TLS 1.2的支持择懂。
常用的有下面這些:
SSL 2.0,SSL 3.0另玖,TLS 1.0 (SSL 3.1)休蟹,TLS 1.1 (SSL 3.1),TLS 1.2 (SSL 3.1)
那為什么標題是“使用HTTPS”而沒有提及SSL和TLS什么事日矫? “SSL/TLS”跟HTTP和HTTPS有什么關(guān)系?
要理解這個绑榴,要看下他們之間的關(guān)系:
HTTP+SSL/TLS+TCP = HTTPS
或者: HTTPS = “HTTP over SSL”
也就是說:Apple讓你的HTTP采用SSL/TLS協(xié)議哪轿,就是讓你從HTTP轉(zhuǎn)到HTTPS。而這一做法翔怎,官方文檔稱為ATS窃诉,全稱為App Transport Security。
以前的HTTP不是也能用嗎赤套?為什么要用SSL/TLS飘痛?
不使用SSL/TLS的HTTP通信,就是不加密的通信容握!
不使用SSL/TLS的HTTP通信宣脉,所有信息明文傳播,帶來了三大風(fēng)險:
竊聽風(fēng)險(eavesdropping):第三方可以獲知通信內(nèi)容剔氏。
篡改風(fēng)險(tampering):第三方可以修改通信內(nèi)容塑猖。
冒充風(fēng)險(pretending):第三方可以冒充他人身份參與通信竹祷。
SSL/TLS協(xié)議是為了解決這三大風(fēng)險而設(shè)計的,希望達到:
所有信息都是加密傳播羊苟,第三方無法竊聽塑陵。
具有校驗機制,一旦被篡改蜡励,通信雙方會立刻發(fā)現(xiàn)令花。
配備身份證書,防止身份被冒充凉倚。
SSL/TLS的作用兼都,打個比方來講:
如果原來的 HTTP 是塑料水管,容易被戳破占遥;那么如今新設(shè)計的 HTTPS 就像是在原有的塑料水管之外俯抖,再包一層金屬水管(SSL/TLS協(xié)議)。一來瓦胎,原有的塑料水管照樣運行芬萍;二來,用金屬加固了之后搔啊,不容易被戳破柬祠。
如何適配
TLS 1.2 協(xié)議 強制增強數(shù)據(jù)訪問安全 系統(tǒng) Foundation 框架下的“相關(guān)網(wǎng)絡(luò)請求”將不再默認使用 HTTP 等不安全的網(wǎng)絡(luò)協(xié)議,而默認采用 TLS 1.2负芋。服務(wù)器因此需要更新漫蛔,以解析相關(guān)數(shù)據(jù)。如不更新旧蛾,可通過在 Info.plist 中聲明莽龟,倒退回不安全的網(wǎng)絡(luò)請求。
方案一:立即讓公司的服務(wù)端升級使用TLS 1.2锨天,以解析相關(guān)數(shù)據(jù)毯盈。
方案二:雖Apple不建議,但可通過在 Info.plist 中聲明病袄,倒退回不安全的網(wǎng)絡(luò)請求依然能讓App訪問指定http搂赋,甚至任意的http DemoGitHub - ChenYilong/iOS9AdaptationTips: iOS9適配系列教程(iOS9開發(fā)學(xué)習(xí)交流群:541317935)
蘋果官方提供了一些可選配置項來決定是否開啟ATS模式,也就是可以選擇開啟或者不開啟益缠。
開發(fā)者可以針對某些確定的URL不使用ATS脑奠,這需要在工程中的info.plist中標記NSExceptionDomains。在NSExceptionDomains字典中幅慌,可以顯式的指定一些不使用ATS的URL宋欺。這些你可以使用的例子可以是:
NSIncludesSubdomains
NSExceptionAllowInsecureHTTPLoads
NSExceptionRequiresForwardSecrecy
NSExceptionMinimumTLSVersion
NSThirdPartyExceptionAllowsInsecureHTTPLoads
NSThirdPartyExceptionMinimumTLSVersion
NSThirdPartyExceptionRequiresForwardSecrecy
這些關(guān)鍵字使我們可以更加細致的設(shè)置針對不使用ATS的域名情況下禁用ATS或者一些特殊的ATS選項。
你可能注意到一些關(guān)鍵字像是使用了一些其他關(guān)鍵字中的詞但是在前面加上了"ThirdParty"字樣迄靠,比如列表里最后三個:
NSThirdPartyExceptionAllowsInsecureHTTPLoads
NSThirdPartyExceptionMinimumTLSVersion
NSThirdPartyExceptionRequiresForwardSecrecy
在功能上秒咨,這些關(guān)鍵字與不含有"ThirdParty"的關(guān)鍵字有同樣的效果。而且實際運行中所調(diào)用的代碼將會完全忽略是否使用"ThirdParty"關(guān)鍵字掌挚。你應(yīng)該使用適用于你的場景的關(guān)鍵字而不必過多考慮這些雨席。
1.HTTPS Only (只有HTTPS,所有情況下都使用ATS)
如果你的應(yīng)用只基于支持HTTPS的服務(wù)器吠式,那么你太幸運了陡厘。你的應(yīng)用不需要做任何改變。
唯一需要做的事情就是使用 NSURLSession 特占。如果你的開發(fā)目標是iOS 9或者 OS X EI Capitan之后糙置,ATS 的最佳實踐將會應(yīng)用到所有基于 NSURLSession 的網(wǎng)絡(luò)。
但也有人遇到過這樣的疑惑:服務(wù)器已支持TLS 1.2 SSL 是目,但iOS9上還是不行院领,還要進行本文提出的適配操作殃恒。
那是因為:要注意 App Transport Security 要求 TLS 1.2伶跷,而且它要求站點使用支持forward secrecy協(xié)議的密碼熏兄。證書也要求是符合ATS規(guī)格的,ATS只信任知名CA頒發(fā)的證書嗤疯,小公司所使用的 self signed certificate冤今,還是會被ATS攔截。茂缚。因此慎重檢查與你的應(yīng)用交互的服務(wù)器是不是符合ATS的要求非常重要戏罢。對此,建議使用下文中給出的NSExceptionDomains脚囊,并將你們公司的域名掛在下面龟糕。
2.Mix & Match(混合)
你的應(yīng)用與一個不符合ATS要求的服務(wù)器工作是很有可能的,
當你遇到以下三個不符合 ATS 要求的服務(wù)器的域名時:
api.insecuredomain.com
cdn.domain.com
thatotherdomain.com
你可以分別設(shè)置如下:
api.insecuredomain.com
我們定義的第一個“例外”(Exception)告訴ATS當與這個子域交互的時候撤銷了必須使用HTTPS的要求悔耘。注意這個僅僅針對在“例外”(Exception)中聲明了的子域翩蘸。非常重要的一點是要理解NSExceptionAllowsInsecureHTTPLoads關(guān)鍵字并不僅僅只是與使用HTTPS相關(guān)。這個“例外”(Exception)指明了對于那個域名淮逊,所有的App Transport Security的要求都被撤銷了。
很可能你的應(yīng)用是與一個支持HTTPS傳輸數(shù)據(jù)的服務(wù)器交互扶踊,但是并沒有使用TLS 1.2或更高泄鹏。在這種情況下,你定義一個“例外”(Exception)秧耗,它指明應(yīng)該使用的最小的TLS的版本备籽。這比完全撤銷那個域名的App Transport Security要更好更安全。
thatotherdomain.com
3. Opt Out(禁用ATS)
上面是比較嚴謹?shù)淖龇ǎ付四茉L問哪些特定的HTTP车猬。當然也有暴力的做法: 徹底倒退回不安全的HTTP網(wǎng)絡(luò)請求霉猛,能任意進行HTTP請求,比如你在開發(fā)一款瀏覽器App珠闰,或者你想偷懶惜浅,或者后臺想偷懶,或者公司不給你升級服務(wù)器伏嗜。坛悉。。
4. Opt Out With Exceptions(除特殊情況外承绸,都不使用ATS)
上面已經(jīng)介紹了三種情景裸影,還有一種可能你也會遇到:
當你的應(yīng)用撤消了App Transport Security,,但同時定義了一些“例外”(Exception)军熏。當你的應(yīng)用從很多的服務(wù)器上取數(shù)據(jù)轩猩,但是也要與一個你可控的API交互。在這種情況下荡澎,在應(yīng)用的Info.plist文件中指定任何加載都是被允許的均践,但是你也指定了一個或多個“例外”(Exception)來表明哪些是必須要求 App Transport Security的。下面是Info.plist文件應(yīng)該會有的內(nèi)容:
5.Certificate Transparency
雖然ATS大多數(shù)安全特性都是默認可用的衔瓮,Certificate Transparency 是必須設(shè)置的浊猾。如果你有支持Certificate Transparency的證書,你可以檢查NSRequiresCertificateTransparency關(guān)鍵字來使用Certificate Transparency热鞍。再次強調(diào)葫慎,如果你的證書不支持Certificate Transparency,此項需要設(shè)置為不可用薇宠。
如果需要調(diào)試一些由于采用了ATS而產(chǎn)生的問題偷办,需要設(shè)置CFNETWORK_DIAGNOSTICS為1,這樣就會打印出包含被訪問的URL和ATS錯誤在內(nèi)的NSURLSession錯誤信息澄港。要確保處理了遇到的所有的錯誤消息椒涯,這樣才能使ATS易于提高可靠性和擴展性。
6.Q-A
Q:我用xcode7編譯的app回梧,如果不在plist里面加關(guān)鍵字說明废岂,ios9下不能進行網(wǎng)絡(luò)請求,因為我們服務(wù)器并不支持 TLS 1.2 狱意,我要是直接下載app store上的湖苞,什么也沒有做,也是能正常網(wǎng)絡(luò)請求详囤。
A:本文中所羅列的新特性财骨,多數(shù)情況下指的是 iOS9.X-SDK 新特性,AppStore 的版本是基于 iOS8.X-SDK或 iOS7.X-SDK,所以并不受 iOS9新特性約束隆箩。也就是說:Xcode7給iOS8打設(shè)備包可以請求到網(wǎng)絡(luò)该贾,Xcode7給iOS9設(shè)備打的包請求不到網(wǎng)絡(luò),Xcode7和iOS9缺一不可捌臊,才需要網(wǎng)絡(luò)適配ATS杨蛋。
那么,如何確認自己項目所使用的 SDK娃属?在Targets->Build Setting-->Architectures
Q:服務(wù)器已支持TLS 1.2 SSL 六荒,但iOS9上還是不行,還要進行本文提出的適配操作矾端。
A:那是因為:要注意 App Transport Security 要求 TLS 1.2掏击,而且它要求站點使用支持forward secrecy協(xié)議的密碼。證書也要求是符合ATS規(guī)格的秩铆,ATS只信任知名CA頒發(fā)的證書砚亭,小公司所使用的 self signed certificate,還是會被ATS攔截殴玛。捅膘。因此慎重檢查與你的應(yīng)用交互的服務(wù)器是不是符合ATS的要求非常重要。對此滚粟,建議使用下文中給出的NSExceptionDomains寻仗,并將你們公司的域名掛在下面。
官方文檔App Transport Security Technote對CA頒發(fā)的證書要求:
Certificates must be signed using a SHA256 or better signature hash algorithm, with either a 2048 bit or greater RSA key or a 256 bit or greater Elliptic-Curve (ECC) key. Invalid certificates result in a hard failure and no connection
Q:我使用的是第三方的網(wǎng)絡(luò)框架凡壤,比如 AFNetworking 署尤、ASIHTTPRequest、CFSocket 等亚侠,這個有影響沒有曹体?
A: AFNetworking 有影響,其它沒影響硝烂。
ATS 是只針對 NSURLConnection 箕别、 CFURL 、 NSURLSession 滞谢,如果底層涉及到這三個類就會有影響串稀。
現(xiàn)在的 AFNetworking 的 AFHTTPRequestOperationManager 實現(xiàn)是使用的 NSURLConnection 。
但 AFNetworking 也有更新計劃狮杨,移除 NSURLConnection 相關(guān)API母截,遷移到 AFHTTPSessionManager ,但還未執(zhí)行禾酱,詳情見:https://github.com/AFNetworking/AFNetworking/issues/2806。
Q:試了一下禁用 ATS 的方法 但是還是無法聯(lián)網(wǎng) 仍然提示要使用https?
App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.
The resource could not be loaded because the App Transport Security policy requires the use of a secure connection.
A:遇到這類問題,90%是出現(xiàn)在“一個 Project 多 Target ”的情況下颤陶,所以 請確保你修改的颗管,確實是你的 Target 所屬的 Info.plist !
如何確認滓走?請前往這里垦江,確認你 Target 所屬的 Info.plist 究竟是哪個:
Project -> Your Target -> Build Settings -> Info.plist File
或者更直截了當一點,直接修改:
Project -> Your Target —>info-> Custom iOS target properties-> 添加禁用 ATS 的屬性
還有一種可能性是:禁用 ATS 的代碼粘貼進 plist 時搅方,位置不對比吭,可以嘗試放在 第五行
Q:我的項目是“一個 Project 多 Target ”,按照本文禁用 ATS 的方法姨涡,是不是每個 Info.plist 都要修改衩藤?
A:不需要,用到哪個 Target 修改哪個的 Info.plist 涛漂,Target 是獨立的赏表,不受其他 Target 的影響,也不會影響其他 Target匈仗。
Q:如何檢測我們公司 HTTPS 是否符合 ATS 的要求瓢剿?
A: 如果你的 App 的服務(wù)也在升級以適配ATS要求,可以使用如下的方式進行校驗:
在OS X EI Capitan系統(tǒng)的終端中通過nscurl命令來診斷檢查你的HTTPS服務(wù)配置是否滿足Apple的ATS要求:
$?nscurl?--verbose?--ats-diagnostics?https://
當然悠轩,你也可以讓公司服務(wù)端的同事參考Apple提供官方指南App Transport Security Technote進行服務(wù)的升級配置以滿足ATS的要求:
一個符合 ATS 要求的 HTTPS间狂,應(yīng)該滿足如下條件:
Transport Layer Security協(xié)議版本要求TLS1.2以上
服務(wù)的Ciphers配置要求支持Forward Secrecy等
證書簽名算法符合ATS要求等
2.更靈活的后臺定位
【iOS9在定位的問題上,有一個壞消息一個好消息】壞消息:如果不適配iOS9火架,就不能偷偷在后臺定位(不帶藍條鉴象,見圖)!好消息:將允許出現(xiàn)這種場景:同一App中的多個location manager:一些只能在前臺定位距潘,另一些可在后臺定位炼列,并可隨時開啟或者關(guān)閉特定location manager的后臺定位。
如果沒有請求后臺定位的權(quán)限音比,也是可以在后臺定位的俭尖,不過會帶藍條: enter image description here
如何偷偷在后臺定位:請求后臺定位權(quán)限:
//?1.?實例化定位管理器
_locationManager?=?[[CLLocationManager?alloc]?init];
//?2.?設(shè)置代理
_locationManager.delegate?=?self;
//?3.?定位精度
[_locationManager?setDesiredAccuracy:kCLLocationAccuracyBest];
//?4.請求用戶權(quán)限:分為:①只在前臺開啟定位②在后臺也可定位,
//注意:建議只請求①和②中的一個洞翩,如果兩個權(quán)限都需要稽犁,只請求?即可,
//①②這樣的順序骚亿,將導(dǎo)致bug:第一次啟動程序后已亥,系統(tǒng)將只請求①的權(quán)限,②的權(quán)限系統(tǒng)不會請求来屠,只會在下一次啟動應(yīng)用時請求?
if([[[UIDevice?currentDevice]?systemVersion]?floatValue]?>=?8)?{
//[_locationManager?requestWhenInUseAuthorization];//?只在前臺開啟定位
[_locationManager?requestAlwaysAuthorization];//?在后臺也可定位
}
//?5.iOS9新特性:將允許出現(xiàn)這種場景:同一app中多個location?manager:一些只能在前臺定位虑椎,另一些可在后臺定位(并可隨時禁止其后臺定位)震鹉。
if([[[UIDevice?currentDevice]?systemVersion]?floatValue]?>=?9)?{
_locationManager.allowsBackgroundLocationUpdates?=?YES;
}
//?6.?更新用戶位置
[_locationManager?startUpdatingLocation];
但是如果照著這種方式嘗試,而沒有配置Info.plist捆姜,100%你的程序會崩潰掉传趾,并報錯:
*** Assertion failure in -[CLLocationManager setAllowsBackgroundLocationUpdates:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/CoreLocationFramework_Sim/CoreLocation-1808.1.5/Framework/CoreLocation/CLLocationManager.m:593
3.企業(yè)級分發(fā)
有兩處變化:
iOS9以后,企業(yè)級分發(fā)ipa包將遭到與Mac上dmg安裝包一樣的待遇:默認不能安裝泥技,也不再出現(xiàn)“信任按鈕”
iOS9以后浆兰,企業(yè)分發(fā)時可能存在:下載的ipa包與網(wǎng)頁兩者的 bundle ID 無法匹配而導(dǎo)致下載失敗的情況
1. iOS9以后,企業(yè)級分發(fā)ipa包將遭到與Mac上dmg安裝包一樣的待遇:默認不能安裝珊豹,也不再出現(xiàn)“信任按鈕”
iOS9之前簸呈,企業(yè)級分發(fā)十分方便:點擊App出現(xiàn)“信任按鈕”,
iOS9以后店茶,企業(yè)級分發(fā)ipa包將遭到與Mac上dmg安裝包一樣的待遇:默認不能安裝蜕便,也不再出現(xiàn)“信任按鈕”
2. iOS9以后,企業(yè)分發(fā)時可能存在:下載的ipa包與網(wǎng)頁兩者的 bundle ID 無法匹配而導(dǎo)致下載失敗的情況
iOS9升級后眾多企業(yè)分發(fā)的 app 已經(jīng)出現(xiàn)了不能安裝的情況忽妒,而iOS8或更早的系統(tǒng)不受影響玩裙。那是因為從iOS9以后,系統(tǒng)會在 ipa 包下載完之后段直,拿ipa包中的 bundle ID 與網(wǎng)頁中的 plist 文件中的 bundle ID 進行比對吃溅,不一致不允許安裝。
網(wǎng)頁中的 plist 文件中的 bundle ID 的作用可參考 《iOS:蘋果企業(yè)證書通過網(wǎng)頁分發(fā)安裝app》 鸯檬。
正如這篇文章提到的决侈,“網(wǎng)頁中的 plist 文件”是習(xí)慣的叫法,也有人稱作“manifest文件”喧务,比如這篇文章赖歌。
而iOS9之前,蘋果不會檢查這一項功茴,因此iOS9之前可以安裝庐冯。
導(dǎo)致這一錯誤的原因除了粗心,還有開發(fā)者是故意設(shè)置不一致坎穿,據(jù)開發(fā)者說:
當初服務(wù)器 plist 的 bundle id 上故意做成成不一致展父。是為了解決一些人安裝不上的問題。
詳情可參考: 《升級到ios 9玲昧,企業(yè)版發(fā)布現(xiàn)在無法安裝成功了栖茉,有人遇到了這種問題嗎?》
如何知道是因為 bundle id 不一致造成的無法安裝孵延?
通過查看設(shè)備上的日志信息:有一個 itunesstored 進程提示安裝信息:
itunesstored?→??:?[Download]:?Download?task?did?finish:?8fordownload:?2325728577585828282
itunesstored?→??:?[ApplicationWorkspace]?Installing?download:?2325728577585828282withstep(s):?Install
itunesstored?→??:?[ApplicationWorkspace]:?Installing?software?packagewithbundleID:?com.***.***:?bundleVersion:?1.01?path:?/var/mobile/Media/Downloads/2325728577585828282/-1925357977307433048
itunesstored?→??:?BundleValidator:?Failed?bundleIdentifier:?com.***.****?does?not?match?expected?bundleIdentifier:?com.***.*********
itunesstored?→??:?[ApplicationWorkspace]:?Bundle?validatedforbundleIdentifier:?com.****.******success:?0
itunesstored?→??:?LaunchServices:?Uninstalling?placeholderforappcom.****.*******(Placeholder)
itunesstored?→??:?LaunchServices:?Uninstalling?appcom.****.*****(Placeholder)
其中的這一句很重要:
itunesstored?→?:?BundleValidator:?Failed?bundleIdentifier:?com.***.****?does?not?match?expected?bundleIdentifier:?com.***.*********
經(jīng)過核對吕漂,果然是.ipa文件中真實的Bundle ID和manifest文件中配置的信息不匹配,然后測試發(fā)現(xiàn):
iOS 9是校驗bundle-identifier值的尘应,而iOS 9以下版本是不校驗惶凝,一旦iOS 9發(fā)現(xiàn)bundle-identifier不匹配吼虎,即使下載成功了,也會 Uninstall(日志中提示的)app的苍鲜。
適配方法:
a.兩者的 bundle id 修改一致
一旦出現(xiàn)iOS9能夠安裝企業(yè)版本APP鲸睛,iOS9以下版本不能安裝,一定先查看安裝日志坡贺,然后核對每個參數(shù)配置。
b.使用fir.im等第三方分發(fā)平臺:上述“ bundle id 不一致導(dǎo)致下載失敗”這種情況只會出現(xiàn)在企業(yè)自己搭建網(wǎng)頁分發(fā)的情形下,事實證明第三方的分發(fā)平臺更加專業(yè)晴股,已經(jīng)很好地規(guī)避了該情況的發(fā)生愿伴。
Q-A
Q:企業(yè)分發(fā),企業(yè)版證書在iOS9上安裝應(yīng)用報 Ignore manifest download, already have bundleID: com.mycom.MyApp 只有我的手機無法安裝电湘,別人 iOS9 都可以安裝
A:這并非 iOS9的問題隔节,iOS8及以前的系統(tǒng)也會出現(xiàn),和緩存有關(guān)系寂呛,請嘗試關(guān)機重啟手機怎诫,然后就可以安裝了。
4.Bitcode
【前言】未來贷痪, Watch 應(yīng)用必須包含 bitcode 幻妓,iOS不強制,Mac OS不支持劫拢。 但最坑的一點是: Xcode7 及以上版本會默認開啟 bitcode 肉津。
什么是 bitcode ?
通俗解釋:在線版安卓ART模式舱沧。
bitcode 是被編譯程序的一種中間形式的代碼妹沙。包含 bitcode 配置的程序?qū)?App Store 上被編譯和鏈接。 bitcode 允許蘋果在后期重新優(yōu)化我們程序的二進制文件熟吏,而不需要我們重新提交一個新的版本到 App Store 上距糖。
當我們提交程序到 App Store上時, Xcode 會將程序編譯為一個中間表現(xiàn)形式( bitcode )分俯。然后 App store 會再將這個 bitcode 編譯為可執(zhí)行的64位或32位程序肾筐。
再看看這兩段描述都是放在App Thinning(App瘦身)一節(jié)中,可以看出其與包的優(yōu)化有關(guān)了缸剪。
打個比方吗铐,沒有 bitcode 的 AppStore 里所提供的 App,類似在新華書店里賣捆綁銷售的《四大名著叢書--精裝版》杏节,要買只能全買走唬渗,有了 bitcode 就好比這套四大名著每本都可以單賣典阵,顧客就能按需購買。我們開發(fā)者在這個過程中扮演的角色是圖書出版商的角色镊逝,應(yīng)該照顧那些沒錢一次買四本的顧客壮啊。(不要做不珍惜用戶流量和存儲空間的奸商。撑蒜。)
那為什么第三方的 SDK 不支持 bitcode歹啼,我的 app 也就不能支持?打個比方座菠,《四大名著叢書》只要有一本是可以單賣的狸眼,那么你很難再賣捆綁銷售款的《四大名著叢書》了,所以干脆全都可以單賣浴滴,這大概就是 Apple 的邏輯拓萌。
開發(fā)者都知道,當前 iOS App 的編譯打包方式是把適配兼容多個設(shè)備的執(zhí)行文件及資源文件合并一個文件升略,上傳和下載的文件則包含了所有的這些文件微王,導(dǎo)致占用較多的存儲空間。
App Thinning是一個關(guān)于節(jié)省iOS設(shè)備存儲空間的功能品嚣,它可以讓iOS設(shè)備在安裝炕倘、更新及運行App等場景中僅下載所需的資源,減少App的占用空間翰撑,從而節(jié)省設(shè)備的存儲空間激才。
根據(jù)Apple官方文檔的介紹,App Thinning主要有三個機制:
①Slicing
開發(fā)者把App安裝包上傳到AppStore后额嘿,Apple服務(wù)會自動對安裝包切割為不同的應(yīng)用變體(App variant)瘸恼,當用戶下載安裝包時,系統(tǒng)會根據(jù)設(shè)備型號下載安裝對應(yīng)的單個應(yīng)用變體册养。
②On-Demand Resources
ORD(隨需資源)是指開發(fā)者對資源添加標簽上傳后东帅,系統(tǒng)會根據(jù)App運行的情況,動態(tài)下載并加載所需資源球拦,而在存儲空間不足時靠闭,自動刪除這類資源。
Bitcode 開啟Bitcode編譯后坎炼,可以使得開發(fā)者上傳App時只需上傳Intermediate Representation(中間件)愧膀,而非最終的可執(zhí)行二進制文件。 在用戶下載App之前谣光,AppStore會自動編譯中間件檩淋,產(chǎn)生設(shè)備所需的執(zhí)行文件供用戶下載安裝。
(喵大(@onevcat)在其博客 《開發(fā)者所需要知道的 iOS 9 SDK 新特性》 中也描述了iOS 9中蘋果在App瘦身中所做的一些改進萄金,大家可以轉(zhuǎn)場到那去研讀一下蟀悦。)
其中媚朦,Bitcode的機制可以支持動態(tài)的進行App Slicing,而對于Apple未來進行硬件升級的措施日戈,此機制可以保證在開發(fā)者不重新發(fā)布版本的情況下而兼容新的設(shè)備询张。
Bitcode 是一種中間代碼,那它是什么格式的呢浙炼? LLVM 官方文檔有介紹這種文件的格式:LLVM Bitcode File Format份氧。
如果你的應(yīng)用也準備啟用 Bitcode 編譯機制,就需要注意以下幾點:
Xcode 7默認開啟 Bitcode 弯屈,如果應(yīng)用開啟 Bitcode半火,那么其集成的其他第三方庫也需要是 Bitcode 編譯的包才能真正進行 Bitcode 編譯
開啟 Bitcode 編譯后,編譯產(chǎn)生的 .app 體積會變大(中間代碼季俩,不是用戶下載的包),且 .dSYM 文件不能用來崩潰日志的符號化(用戶下載的包是 Apple 服務(wù)重新編譯產(chǎn)生的梅掠,有產(chǎn)生新的符號文件)
通過 Archive 方式上傳 AppStore 的包酌住,可以在Xcode的Organizer工具中下載對應(yīng)安裝包的新的符號文件
如何適配?
在上面的錯誤提示中阎抒,提到了如何處理我們遇到的問題:
You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture arm64
正如開頭所說的:
未來酪我, Watch 應(yīng)用必須包含 Bitcode ,iOS不強制且叁,Mac OS不支持都哭。 但最坑的一點是: Xcode7 及以上版本會默認開啟 Bitcode 。
Xcode 7 + 會開啟 Bitcode逞带。
也就是說欺矫,也兩種方法適配:
方法一:更新 library 使包含 Bitcode ,否則會出現(xiàn)以下中的警告展氓;
(null): URGENT: all bitcode will be dropped because '/Users/myname/Library/Mobile Documents/com~apple~CloudDocs/foldername/appname/GoogleMobileAds.framework/GoogleMobileAds(GADSlot+AdEvents.o)' was built without bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. Note: This will be an error in the future.
甚至有的會報錯誤穆趴,無法通過編譯:
ld: ‘/Users//Framework/SDKs/PolymerPay/Library/mobStat/libSDK.a(**ForSDK.o)’ does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture arm64
ld: -undefined and -bitcode_bundle (Xcode setting ENABLE_BITCODE =YES) cannot be used together clang: error: linker command failed with exit code 1 (use -v to see invocation)
enter image description here
無論是警告還是錯誤,得到的信息是:我們引入的一個第三方庫不包含bitcode遇汞。
我們可以在”Build Settings”->”Enable Bitcode”選項中看到:
用 Xcode 7+ 新建一個 iOS 程序時未妹, bitcode 選項默認是設(shè)置為YES的。現(xiàn)在需要改成NO空入。
如果我們開啟了 bitcode 络它,在提交包時,下面這個界面也會有個 bitcode 選項:
5. URL Scheme 適配_引入白名單概念
也就是說:在iOS9中歪赢,如果使用 canOpenURL: 方法化戳,該方法所涉及到的 URL scheme 必須在"Info.plist"中將它們列為白名單,否則不能使用埋凯。key叫做LSApplicationQueriesSchemes 迂烁,鍵值內(nèi)容是
iOS9中 openURL: 方法沒有什么實質(zhì)性的變化看尼,僅僅多了一個確認動作:
蘋果為什么要這么做?
在 iOS9 之前盟步,你可以使用 canOpenURL: 監(jiān)測用戶手機里到底裝沒裝微信藏斩,裝沒裝微博。但是也有一些別有用心的 App 却盘,這些 App 有一張常用 App 的 URL scheme狰域,然后他們會多次調(diào)用canOpenURL: 遍歷該表,來監(jiān)測用戶手機都裝了什么 App 黄橘,比如這個用戶裝了叫“大姨媽”的App兆览,你就可以知道這個用戶是女性,你就可以只推給這個用戶女性用品的廣告塞关。這是侵犯用戶隱私的行為抬探。
主要演示的情景是這樣的:
假設(shè)有兩個App: weixin(微信) and 我的App. 我的App 想監(jiān)測 weixin(微信) 是否被安裝了. "weixin(微信)" 在 info.plist 中定義了 URL scheme :
我的App 想監(jiān)測 weixin(微信) 是否被安裝了 :
即使你安裝了微信,在iOS9中帆赢,這有可能會返回NO:
因為你需要將 "weixin(微信)" 添加到 “我的App” 的 info.plist 文件中:
(以上只是為了演示小压,實際開發(fā)中,你不僅需要添加“weixin”還需要“wechat”這兩個椰于。具體 )
推薦一篇博文怠益,其中最關(guān)鍵的是以下部分
If you call the “canOpenURL” method on a URL that is not in your whitelist, it will return “NO”, even if there is an app installed that has registered to handle this scheme. A “This app is not allowed to query for scheme xxx” syslog entry will appear.
常見 URL Scheme 參考
iOS9適配 之 關(guān)于info.plist 第三方登錄 添加URL Schemes白名單 - 簡書
如果想一次性集成最常用的微信、新浪微博瘾婿、QQ蜻牢、支付寶四者的白名單,則配置如下:
其他平臺可在下面的列表中查詢: 各平臺OpenURL白名單說明:
Q-A
Q:我用xcode7編譯的app偏陪,如果不在plist里面加scheme抢呆,ios9下qq就會不顯示,因為我用了qqsdk里的判斷是否安裝qq的方法笛谦,我要是直接下載app store上的镀娶,沒有加scheme,qq也是能顯示揪罕。
A:本文中所羅列的新特性梯码,多數(shù)情況下指的是 iOS9.X-SDK 新特性讶踪,AppStore 的版本是基于 iOS8.X-SDK或 iOS7.X-SDK亲桥,所以并不受 iOS9新特性約束。也就是說:Xcode7給iOS8打設(shè)備包不需要白名單也能調(diào)用“canOpenURL” 沾凄,Xcode7給iOS9設(shè)備打的包則不然框往,Xcode7和iOS9缺一不可鳄抒,才需要適配URL Scheme。
那么,如何確認自己項目所使用的 SDK许溅?在Targets->Build Setting-->Architectures
Q:我們自己的應(yīng)用跳到微信瓤鼻、支付寶、微博等的URLScheme是固定幾個贤重,但是從微信茬祷、支付寶、微博跳回到我們的應(yīng)用的URLScheme可能是成千上萬個并蝗,那他們那些大廠是如何做這個白名單祭犯?
A:白名單策略影響的僅僅是 canOpenURL: 接口,OpenURL: 不受影響滚停,這些大廠只調(diào)用 openURL: 所以不受 iOS9 的影響沃粗。
Q:文中提到了設(shè)置白名單的原因,然而键畴,如果這些別有用心的APP在它自己的白名單列出它關(guān)心的APP, 然后依次調(diào)用canOpenURL來檢測最盅,照樣可以監(jiān)控用戶都安裝了哪些APP啊起惕?所以我依然不明白蘋果這樣做得原因涡贱。
A:白名單的數(shù)目上限是50個。蘋果這樣子做疤祭,使得最多只能檢測50個App。
Q:按照文中的適配方法饵婆,error原因就沒有了的確沒問題了勺馆,但是還是會打印如下信息:
-canOpenURL:?failedforURL:"XXXXXXXXXX"-?error:"(null)"。(我就遇到了侨核。草穆。。搓译。悲柱。。些己。求解)
A:這個模擬器的一個 bug豌鸡,無論使用iOS9的真機還是模擬器均出現(xiàn)該問題,估計 Xcode 后續(xù)的升級中會修復(fù)掉段标。
那如何判斷日志究竟是 Xcode bug 造成的還是沒有適配造成的涯冠?看error的值,如果是null逼庞,則是 bug蛇更。
6. iPad適配Slide Over 和 Split View
【iPad適配Slide Over 和 Split View】 若想適配multi tasking特性,唯一的建議:棄純代碼,改用storyboard派任、xib砸逊,縱觀蘋果WWDC所有Demo均是如此:
7.字體間隙變大導(dǎo)致 UI 顯示異常
iOS8中,字體是Helvetica掌逛,中文的字體有點類似于“華文細黑”师逸。只是蘋果手機自帶渲染,所以看上去可能比普通的華文細黑要美觀颤诀。iOS9中字旭,中文系統(tǒng)字體變?yōu)榱藢橹袊O(shè)計的“蘋方” 有點類似于一種word字體“幼圓”。字體有輕微的加粗效果崖叫,并且最關(guān)鍵的是字體間隙變大了遗淳!
所以很多原本寫死了width的label可能會出現(xiàn)“...”的情況:
如果不將 label 的 width 寫死,僅僅添加左端約束則右端的四個數(shù)字會越界
所以為了在界面顯示上不出錯心傀,就算是固定長度的文字也還是建議使用sizetofit 或者ios向上取整 ceilf() 或者提前計算:
CGSize size = [title sizeWithAttributes:@{NSFontAttributeName: [UIFont systemFontOfSize:14.0f]}];
CGSize adjustedSize = CGSizeMake(ceilf(size.width), ceilf(size.height));
8.升級 Xcode7 后的崩潰與警告
舊版本新浪微博 SDK 在 iOS9 上會導(dǎo)致的 Crash
app was compiled with optimization - stepping may behave oddly; variables may not be available
打印出來這句話屈暗,然后崩潰。多是啟動的過程中程序就崩潰脂男。
在iOS9下养叛,新浪微博SDK里面使用的 JSONKit 在部分機型可能導(dǎo)致崩潰。崩潰信息如下圖宰翅。
解決:更新新浪微博SDK弃甥,新浪的SDK最新版做了對iOS9兼容。
iOS9 下使用 Masonry 會引起崩潰的一種情況
我們在使用時候一直將 leading 與 left 劃為等號汁讼,這樣做在 iOS8(及以前)上是正常的淆攻,但在 iOS9 上這樣的觀念可能會引起崩潰,比如:
make.left.equalTo(self.mas_leading).offset(15);
make.left.equalTo(self.mas_left).offset(15);
同理 mas_training 也需要改為right
Xcode 升級后嘿架,舊的狀態(tài)欄的樣式設(shè)置方式會引起警告
:?CGContextSaveGState:?invalid?context?0x0.?If?you?want?to?see?the?backtrace,?please?set?CG_CONTEXT_SHOW_BACKTRACE?environmental?variable.:?CGContextTranslateCTM:?invalid?context?0x0.?If?you?want?to?see?the?backtrace,?please?set?CG_CONTEXT_SHOW_BACKTRACE?environmental?variable.:?CGContextRestoreGState:?invalid?context?0x0.?If?you?want?to?see?the?backtrace,?please?set?CG_CONTEXT_SHOW_BACKTRACE?environmental?variable.
出錯原因:設(shè)置 app 的狀態(tài)欄樣式的時候瓶珊,使用了舊的方式,在 info.plist 里面的 View controller-based status bar appearance 默認會為 YES耸彪,即使不設(shè)置也是 YES伞芹,但一般 iOS6 的時候為了設(shè)置狀態(tài)欄樣式,需要將其設(shè)為NO蝉娜,iOS7唱较,8也兼容,但是到了iOS9 就會報警告召川。
解決辦法:
刪除原先的設(shè)置代碼绊汹,通常老的設(shè)置方式是這樣的:
//設(shè)置狀態(tài)欄的白色
[[UIApplication?sharedApplication]?setStatusBarStyle:UIStatusBarStyleLightContent];
刪除的原因見下:
//?Setting?the?statusBarStyle?does?nothing?if?your?application?is?using?the?default?UIViewController-based?status?bar?system.
@property(readwrite,?nonatomic)?UIStatusBarStyle?statusBarStyle?NS_DEPRECATED_IOS(2_0,?9_0,"Use?-[UIViewController?preferredStatusBarStyle]");
-?(void)setStatusBarStyle:(UIStatusBarStyle)statusBarStyle?animated:(BOOL)animated?NS_DEPRECATED_IOS(2_0,?9_0,"Use?-[UIViewController?preferredStatusBarStyle]");
修改方式是在 Info.plist 文件中做如下修改:
將 View controller-based status bar appearance 刪除(默認為 YES),或設(shè)置為YES:
對應(yīng)的 plist 里的 XML源碼:
UIViewControllerBasedStatusBarAppearance
看起來長這樣:
然后使用新的方式來實現(xiàn)狀態(tài)欄的樣式:
-?(UIStatusBarStyle)preferredStatusBarStyle;
-?(UIViewController?*)childViewControllerForStatusBarStyle;
-?(void)setNeedsStatusBarAppearanceUpdate
比如扮宠,你想將狀態(tài)欄設(shè)置為白色西乖,就可以這樣寫:
//設(shè)置狀態(tài)欄的白色
-(UIStatusBarStyle)preferredStatusBarStyle
{
returnUIStatusBarStyleLightContent;
}
記得要 clean 下或者刪除應(yīng)用程序重新運行狐榔。
Demo4---navigationController狀態(tài)欄樣式新的設(shè)置方法
如果你按照上面的方法設(shè)置了,但還是不行获雕。八成是 rootViewController 設(shè)置的問題薄腻,你必須設(shè)置 rootViewController,編譯器才會去 rootViewController 中重載 preferredStatusBarStyle 方法届案。
另外當你在 appdelegate 中將 navigationController 設(shè)為 rootViewController 的時候:
self.window.rootViewController?=?self.navigationController;
因為 rootViewController 變?yōu)榱?navigationController庵楷,你在 ViewController 里重寫 preferredStatusBarStyle 方法是不會起作用的。所以最好的方法是
-?(void)viewDidLoad
{
[superviewDidLoad];
self.title?=?@"微博@iOS程序犭袁";
self.navigationController.navigationBar.barStyle?=?UIBarStyleBlack;
}
如果你還是想重寫 preferredStatusBarStyle 方法來達到作用楣颠,那最好使用分類來解決:
.h文件:
//
//??UINavigationController+StatusBarStyle.h
//??微博@iOS程序犭袁
//
//??Created?byhttps://github.com/ChenYilong/iOS9AdaptationTips/?on?15/6/8.
//??Copyright?(c)?2015年http://weibo.com/luohanchenyilong/??.?All?rights?reserved.
//
#import
@interface?UINavigationController?(StatusBarStyle)
@end
.m文件:
//
//??UINavigationController+StatusBarStyle.m
//??微博@iOS程序犭袁
//
//??Created?byhttps://github.com/ChenYilong/iOS9AdaptationTips/?on?15/6/8.
//??Copyright?(c)?2015年http://weibo.com/luohanchenyilong/??.?All?rights?reserved.
//
#import?"UINavigationController+StatusBarStyle.h"
@implementation?UINavigationController?(StatusBarStyle)
-?(UIStatusBarStyle)preferredStatusBarStyle
{
//also?you?may?add?any?fancy?condition-based?code?here
returnUIStatusBarStyleLightContent;
}
@end
我在倉庫里給出了 navigation 的設(shè)置方法尽纽,見Demo4。
參考鏈接:preferredStatusBarStyle isn't called--For anyone using a UINavigationController:
Xcode7 在 debug 狀態(tài)下也生成 .dSYM 文件引起的警告
Xcode6 的工程升級到 Xcode7上來童漩,會報警告:
這是 debug 編譯時導(dǎo)出符號文件出現(xiàn)的告警弄贿,然而新建的Xcode7工程不會有該問題。
解決方法是讓 debug 編譯的時候不生成符號文件:
Xcode7 無法使用 8.x 系統(tǒng)的設(shè)備調(diào)試矫膨,一運行就報錯 there is an intenal API error
Xcode7 調(diào)試 iOS8.x 的真機差凹,需要確保項目名改為英文,中間含有中文會報錯 there is an intenal API error
按照下面的步驟檢查:
bulid settings -> packaging -> product name
使用了 HTML 的 iframe 元素可能導(dǎo)致無法從 Safari 跳轉(zhuǎn)至 App
我們都知道侧馅,從網(wǎng)易新聞分享一條新聞到QQ危尿,然后從QQ中打開鏈接再用safari打開鏈接,在iOS8上馁痴,這個時候會跳轉(zhuǎn)到網(wǎng)易新聞App谊娇。但是現(xiàn)在(2015年09月23日)版本的網(wǎng)易新聞在 iOS9 就不能正常跳轉(zhuǎn),會跳轉(zhuǎn)到 App Store 頁面并提示要不要打開 App Store罗晕。
這是很可能是因為使用了 HTML 的 iframe 元素济欢,并將自定義的鏈接放進了該元素中
舉例說明:
我之前寫的一個 Demo:模仿 《簡書 App》 的效果:在html中跳轉(zhuǎn)到App中的對應(yīng)頁面,并能從App跳轉(zhuǎn)到原來的網(wǎng)址,在例子中直接調(diào)用自定義鏈接在 iOS9上是可以跳轉(zhuǎn)到 App 中的攀例,然而船逮,如果用 iframe 元素包起來就會變不可用顾腊。
iOS9鎖屏控制臺會打印警告
加入運行如下示例代碼:
-?(void)viewDidLoad?{
[superviewDidLoad];
dispatch_queue_t?queue?=?dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,?0);
dispatch_async(queue,?^(void)?{
//在這個10秒內(nèi)鎖屏
NSLog(@"準備休眠");
sleep(10);
NSLog(@"打印成功");
});
}
應(yīng)用運行過程中鎖屏粤铭,總是會出現(xiàn)以下提示:
**?-[UIApplication?_handleNonLaunchSpecificActions:forScene:withTransitionContext:completion:]?**?unhandled?action?->{
handler?=?remote;
info?={
(1)?=?5;
};
}
當應(yīng)用處于空閑狀態(tài)時(無網(wǎng)絡(luò)請求)鎖屏對于用戶而言并無較大影響,但是當應(yīng)用在執(zhí)行某個異步任務(wù)時(比如下拉刷新一下列表)鎖屏杂靶,重新解鎖進入就可能會發(fā)現(xiàn)異步任務(wù)失敗梆惯,控制臺也會提示 Error 信息:
**?-[UIApplication?_handleNonLaunchSpecificActions:forScene:withTransitionContext:completion:]?**?unhandled?action?->{
handler?=?remote;
info?={
(1)?=?5;
};
}
errorin__connection_block_invoke_2:?Connection?interrupted
以上情況不易復(fù)現(xiàn),但確有發(fā)生吗垮。
在 iOS8 系統(tǒng)下測試并未發(fā)現(xiàn)此問題垛吗。
對此并未找到合理的解釋和對應(yīng)的解決辦法,如果你有解決方法烁登,歡迎提 PR !
10.iOS國際化問題:當前設(shè)備語言字符串返回有變化怯屉。
NSUserDefaults?*defaults?=?[NSUserDefaults?standardUserDefaults];
NSArray?*allLanguage?=?[defaults?objectForKey:@"AppleLanguages"];
NSString?*currentLanguage?=?[allLanguage?objectAtIndex:0];
NSLog(@"The?current?language?is?:?%@",?currentLanguage);
iOS 9 之前:以上返回結(jié)果:語言字符串代碼。例如:"zh-Hans"
iOS 9:以上返回結(jié)果:語言字符串代碼 + 地區(qū)代碼。例如:"zh-Hans-US"
1.請注意判斷當前語言類型锨络,不要用以下形式的代碼了赌躺,不然在iOS9上就會遇到坑。
if([currentLanguage?isEqualToString:@"zh-Hans"])
可以使用:
if([currentLanguage?hasPrefix:@"zh-Hans"])
另外:對于中文羡儿,語言有:
簡體中文:zh-Hans
繁體中文:zh-Hant
香港中文:zh-HK
澳門中文:zh-MO
臺灣中文:zh-TW
新加坡中文:zh-SG
備注:以上iOS9 當前語言字符串返回結(jié)果:語言字符串代碼 + 地區(qū)代碼礼患。在某些情況下不是這樣,本人手機型號:大陸版電信iPhone5S/A1533/16GB測試結(jié)果:zh-HK/zh-TW掠归,在地區(qū)為"中國"缅叠、"中國香港"、"中國臺灣"的時候虏冻,顯示的還是zh-HK/zh-TW肤粱,一旦切換到其它地區(qū),設(shè)備語言會自動的切換到中文繁體兄旬。請開發(fā)人員注意中文的問題狼犯!
參考:iOS 9適配技巧(更新版) - CocoaChina_讓移動開發(fā)更簡單