本文主要是說一些iOS9適配中出現的坑,如果只是要單純的瞭解iOS9新特性可以看瞄神的開發者所需要知道的 iOS 9 SDK 新特性。9月17日凌晨,蘋果給用戶推送了iOS9正式版,隨着有用戶陸續升級iOS9,也就逐漸的衍生出了一系列的問題,筆者也在趕忙爲自己維護的App做適配,本文寫的一些坑基本都是親身體驗了。
一、NSAppTransportSecurity
iOS9讓所有的HTTP默認使用了HTTPS,原來的HTTP協議傳輸都改成TLS1.2協議進行傳輸。直接造成的情況就是App發請求的時候彈出網絡無法連接。解決辦法就是在項目的info.plist 文件里加上如下節點:
NSAppTransportSecurity - NSAllowsArbitraryLoads
這個子節點的意思是:是否允許任性的加載?! 設爲YES的話就將禁用了AppTransportSecurity轉而使用用戶自定義的設置,這個問題就解決了。
如果你不是在董鉑然博客園看到本文,請點擊查看原文。
上面說是蘋果限制了HTTP協議,但是也並不是說所有的HTTPS都能完美適配iOS9了。
舉個栗子,從app內起webView加載https的網頁。新建個項目寫幾行起網頁的代碼
1
2
3
4
5
6
7
8
9
10
11
12
|
-
( void )loadView{ UIWebView
*web = [[UIWebView alloc]initWithFrame:[UIScreen mainScreen].bounds]; self .view
= web; } -
( void )viewDidLoad
{ [ super viewDidLoad]; UIWebView
*web = (UIWebView *) self .view; //董鉑然 NSURLRequest *request
= [ NSURLRequest requestWithURL:url]; [web
loadRequest:request]; } |
中間的url就是我們想要加載的https地址,用https://baidu.com/ 和 https://github.com/ 分別試一下,結果不同
github的網頁能打開,百度的網頁打不開,下面打印了一行log
1
|
NSURLSession / NSURLConnection HTTP
load failed (kCFStreamErrorDomainSSL, -9802) |
原因是蘋果的官方資料說首先必須要基於TLS 1.2版本協議。然後證書的加密的算法還需要達到SHA256或者更高位的RSA密鑰或ECC密鑰,如果不符合,請求將被中斷並返回nil.
在瀏覽器中是可以直接查看這個網站的加密算法的,先點綠鎖再點證書信息。
從右邊兩張圖可以看出,github帶RSA加密的SHA-256符合蘋果的要求,所以纔可以展示。
針對百度的情況可以在info.plist中配置如下,如果網站引用的比較多應該是需要針對每個網站進行配置。
NSAppTransportSecurity,NSExceptionDomains,NSIncludesSubdomains,NSExceptionRequiresForwardSecrecy,NSExceptionAllowInsecureHTTPLoads 寫在下面便於複製。
其中的ForwardSecrecy理解爲超前的密碼保護算法,在官方資料裏有寫,一共是11種。配置完畢百度可以訪問。
二、Bitcode
bitcode的理解應該是把程序編譯成的一種過渡代碼,然後蘋果再把這個過渡代碼編譯成可執行的程序。bitcode也允許蘋果在後期重新優化我們程序的二進制文件,有類似於App瘦身的思想。
用了xcode7的編譯器編譯之前沒問題的項目可能會出現下列報錯。
1
|
XXXX’
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 |
問題的原因是:某些第三方庫還不支持bitcode。要不然是等待庫的開發者升級了此項功能我們更新庫,要不就是把這個bitcode禁用。
禁用的方法就是找到如下配置,選爲NO.(iOS中bitcode是默認YES,watchOS中bitcodes是不讓改的必須YES。)
三、設置信任
這一條只和企業級應用或inhose 有關,和AppStore渠道的應用無關。
在iOS8只是彈出一個窗問你是否需要讓手機信任這個應用,但是在iOS9卻直接禁止,如果真的想信任需要自己去手動開啓。類似於Mac系統從未知開發者處下載的dmg直接打不開,然後要到系統偏好設置的安全性與隱私手動打開。 下圖展示左邊iOS8,右邊iOS9
用戶需要去 設置---》通用---》描述文件 裏面自行添加信任。
這種問題的處理方法也就兩種:1.提前周知暫時不要升級iOS9 2.大多是公司員工使用的企業級應用,羣發一個指導郵件。
四、字體
iOS8中,字體是Helvetica,中文的字體有點類似於“華文細黑”。只是蘋果手機自帶渲染,所以看上去可能比普通的華文細黑要美觀。
iOS9中,中文系統字體變爲了專爲中國設計的“蘋方” 有點類似於一種word字體“幼圓”。字體有輕微的加粗效果,並且最關鍵的是字體間隙變大了!
所以很多原本寫死了width的label可能會出現“...”的情況。
iOS8
iOS9 蛋疼
上面這兩張圖也可以直觀的看出同一個界面,同一個label的變化。
所以爲了在界面顯示上不出錯,就算是固定長度的文字也還是建議使用sizetofit 或者ios向上取整 ceilf() 或者提前計算
1
2
|
CGSize
size = [title sizeWithAttributes:@{ NSFontAttributeName :
[UIFont systemFontOfSize:14.0f]}]; CGSize
adjustedSize = CGSizeMake(ceilf(size.width), ceilf(size.height)); |
五、URL scheme
URL scheme一般使用的場景是應用程序有分享或跳其他平臺授權的功能,分享或授權後再跳回來。
在iOS8並沒有做過多限制,但是iOS9需要將你要在外部調用的URL scheme列爲白名單,纔可以完成跳轉
如果iOS9沒做適配 會報如下錯誤
1
|
canOpenURL:
failed for URL
: "mqzone://qqapp" -
error: "This
app is not allowed to query for scheme mqzone" |
具體的解決方案也是要在info.plist中設置 LSApplicationQueriesSchemes 類型爲數組,下面添加所有你用到的scheme
六、statusbar
這個還好只是報一個警告,如果就是不管他,也不會出現問題。
1
|
<Error>:
CGContextSaveGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable. |
以前我們爲了能夠實時的控制頂部statusbar的樣式,可能會在喜歡使用
1
2
|
[[UIApplication
sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent] [[UIApplication
sharedApplication]setStatusBarHidden: YES ]; |
但是這麼做之前需要將 info.plist 裏面加上View controller-based status bar appearance BOOL值設爲NO,就是把控制器控制狀態欄的權限給禁了,用UIApplication來控制。但是這種做法在iOS9不建議使用了,建議我們使用吧那個BOOL值設爲YES,然後用控制器的方法來管理狀態欄比如。
1
2
3
4
|
-
(UIStatusBarStyle)preferredStatusBarStyle { return UIStatusBarStyleLightContent; } |
點進頭文件可以驗證剛纔說法:
1
|
@property ( readwrite , nonatomic ,getter=isStatusBarHidden) BOOL statusBarHidden NS_DEPRECATED_IOS (2_0,
9_0, "Use
-[UIViewController prefersStatusBarHidden]" ); |
七、didFinishLaunchingWithOptions
如果運行的時候報下列錯誤,那就是你的didFinishLaunchingWithOptions寫的不對了
1
|
*****
Assertion failure in -[UIApplication _runWithMainScene:transitionContext:completion:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3505.16/UIApplication.m:3294** |
iOS9不允許在didFinishLaunchingWithOptions結束了之後還沒有設置window的rootViewController。 也許是xcode7的編譯器本身就不支持。
解決的方法當然就是先初始化個值,之後再賦值替換掉
1
2
|
UIWindow
*window = [[UIWindowalloc] initWithFrame:[UIScreenmainScreen].bounds]; window.rootViewController
= [[UIViewController alloc]init]; |
八、tableView
雖然現在的iOS9已經推送正式版了,但是iOS9使用時還是會感覺到App比以前更加卡頓了,tableView拖動時卡頓顯示的最爲明顯。 並且之前遇到一個bug,原本好的項目用xcode7一編譯,tableView刷新出了問題 ,[tableView reloadData]無效 有一行cell明明改變了但是刷新不出來。 感覺可能是這個方法和某種新加的特性衝突了,猜測可能是reloadData的操作被推遲到下一個RunLoop執行最終失效。
解決的方法是,註釋[tableView reloadData],改用局部刷新,問題居然就解決了。
1
|
[ self .tableView
reloadSections:[ NSIndexSet indexSetWithIndex:0]
withRowAnimation:UITableViewRowAnimationNone]; |
九、NSLocalizableString(XCode7問題)
如果你程序啓動後出現主頁面一片空白,或是報了以下的棧調用錯誤。那就是NSLocalizableString的死循環導致堆棧溢出了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#0
0x003052a8 in -[NSLocalizableString length] () #1
0x003052cc in -[NSLocalizableString length] () #2
0x003052cc in -[NSLocalizableString length] () #3
0x003052cc in -[NSLocalizableString length] () #4
0x003052cc in -[NSLocalizableString length] () #5
0x003052cc in -[NSLocalizableString length] () #6
0x003052cc in -[NSLocalizableString length] () #7
0x003052cc in -[NSLocalizableString length] () #8
0x003052cc in -[NSLocalizableString length] () #9
0x003052cc in -[NSLocalizableString length] () #10
0x003052cc in -[NSLocalizableString length] () #11
0x003052cc in -[NSLocalizableString length] () #12
0x003052cc in -[NSLocalizableString length] () #13
0x003052cc in -[NSLocalizableString length] () #14
0x003052cc in -[NSLocalizableString length] () #15
0x003052cc in -[NSLocalizableString length] () #16
0x003052cc in -[NSLocalizableString length] () |
這個的解決方法就是找到特定的頁面,然後將English 前面的勾勾上。
十、bundle identifier(Xcode7問題)
如果你遇到了在本地編譯通過,但是在CI上打包失敗。並且報的錯誤是和bundle identifier相關,那很有可能是你plist文件中寫的bundle identifier沒有起作用。
因爲xcode7新增了此功能,在target下面的BuildSetting裏面增加了Product Bundle identifier。蘋果之後的做法應該是推薦在此處設置bundle identifier,此處的設置會比info.plist裏面優先讀取。
如果你的Bundle identifier一直沒變,可能不會發現此問題。如果改變了,你在plist中修改是無效的。
另一個做法就是在ci打包的配置Execute shell上增加以下代碼
1
|
"Set
:CFBundleIdentifier com.XXX.XXX" "XXX/Supporting
Files/XXX-Info.plist" |
如果你不是在董鉑然博客園看到本文,請點擊查看原文。
暫時遇到這些問題,感覺iOS9的出現讓所有iOS開發都是菊花一緊,預祝所有的iOS都能及時的做好適配改完bug,下個版本一上線,所有問題都解決。
其他:
在iOS9下,新浪微博SDK裏面使用的JSONKit在部分機型可能導致崩潰。崩潰信息如下圖。
解決:暫時移除新浪微博SDK,等待新浪微博SDK的更新。
影響:移除新浪微博SDK後,除了依賴SDK實現的跳到客戶端的分享和關注官網微博等失效。其他主要功能如分享、SSO、獲取用戶資料等不受影響。
轉載地址:http://www.cnblogs.com/dsxniubility/p/4821184.html