整理iOS9适配中出现的坑(图文)
整理iOS9適配中出現(xiàn)的坑(圖文)
本文主要是說(shuō)一些iOS9適配中出現(xiàn)的坑,如果只是要單純的了解iOS9新特性可以看瞄神的開(kāi)發(fā)者所需要知道的 iOS 9 SDK 新特性。9月17日凌晨,蘋(píng)果給用戶推送了iOS9正式版,隨著有用戶陸續(xù)升級(jí)iOS9,也就逐漸的衍生出了一系列的問(wèn)題,筆者也在趕忙為自己維護(hù)的App做適配,本文寫(xiě)的一些坑基本都是親身體驗(yàn)了。
一、NSAppTransportSecurity
iOS9讓所有的HTTP默認(rèn)使用了HTTPS,原來(lái)的HTTP協(xié)議傳輸都改成TLS1.2協(xié)議進(jìn)行傳輸。直接造成的情況就是App發(fā)請(qǐng)求的時(shí)候彈出網(wǎng)絡(luò)無(wú)法連接。解決辦法就是在項(xiàng)目的info.plist 文件里加上如下節(jié)點(diǎn):
NSAppTransportSecurity -?NSAllowsArbitraryLoads
這個(gè)子節(jié)點(diǎn)的意思是:是否允許任性的加載?! 設(shè)為YES的話就將禁用了AppTransportSecurity轉(zhuǎn)而使用用戶自定義的設(shè)置,這個(gè)問(wèn)題就解決了。
如果你不是在董鉑然博客園看到本文,請(qǐng)點(diǎn)擊查看原文。
?
上面說(shuō)是蘋(píng)果限制了HTTP協(xié)議,但是也并不是說(shuō)所有的HTTPS都能完美適配iOS9了。
舉個(gè)栗子,從app內(nèi)起webView加載https的網(wǎng)頁(yè)。新建個(gè)項(xiàng)目寫(xiě)幾行起網(wǎng)頁(yè)的代碼
| 123456789101112 | - (void)loadView{????UIWebView *web = [[UIWebView alloc]initWithFrame:[UIScreen mainScreen].bounds];????self.view = web;}- (void)viewDidLoad {????[super viewDidLoad];?????????UIWebView *web = (UIWebView *)self.view; //董鉑然????NSURL *url = [NSURL URLWithString:@"https://github.com/"];????NSURLRequest *request = [NSURLRequest requestWithURL:url];????[web loadRequest:request];} |
中間的url就是我們想要加載的https地址,用https://baidu.com/ 和?https://github.com/ 分別試一下,結(jié)果不同
??
github的網(wǎng)頁(yè)能打開(kāi),百度的網(wǎng)頁(yè)打不開(kāi),下面打印了一行l(wèi)og
| 1 | NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802) |
原因是蘋(píng)果的官方資料說(shuō)首先必須要基于TLS 1.2版本協(xié)議。然后證書(shū)的加密的算法還需要達(dá)到SHA256或者更高位的RSA密鑰或ECC密鑰,如果不符合,請(qǐng)求將被中斷并返回nil.
在瀏覽器中是可以直接查看這個(gè)網(wǎng)站的加密算法的,先點(diǎn)綠鎖再點(diǎn)證書(shū)信息。
從右邊兩張圖可以看出,github帶RSA加密的SHA-256符合蘋(píng)果的要求,所以才可以展示。
針對(duì)百度的情況可以在info.plist中配置如下,如果網(wǎng)站引用的比較多應(yīng)該是需要針對(duì)每個(gè)網(wǎng)站進(jìn)行配置。
NSAppTransportSecurity,NSExceptionDomains,NSIncludesSubdomains,NSExceptionRequiresForwardSecrecy,NSExceptionAllowInsecureHTTPLoads 寫(xiě)在下面便于復(fù)制。
其中的ForwardSecrecy理解為超前的密碼保護(hù)算法,在官方資料里有寫(xiě),一共是11種。配置完畢百度可以訪問(wèn)。
? ?
??
二、Bitcode
bitcode的理解應(yīng)該是把程序編譯成的一種過(guò)渡代碼,然后蘋(píng)果再把這個(gè)過(guò)渡代碼編譯成可執(zhí)行的程序。bitcode也允許蘋(píng)果在后期重新優(yōu)化我們程序的二進(jìn)制文件,有類似于App瘦身的思想。
用了xcode7的編譯器編譯之前沒(méi)問(wèn)題的項(xiàng)目可能會(huì)出現(xiàn)下列報(bào)錯(cuò)。
| 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 |
問(wèn)題的原因是:某些第三方庫(kù)還不支持bitcode。要不然是等待庫(kù)的開(kāi)發(fā)者升級(jí)了此項(xiàng)功能我們更新庫(kù),要不就是把這個(gè)bitcode禁用。
禁用的方法就是找到如下配置,選為NO.(iOS中bitcode是默認(rèn)YES,watchOS中bitcodes是不讓改的必須YES。)
?
三、設(shè)置信任
這一條只和企業(yè)級(jí)應(yīng)用或inhose 有關(guān),和AppStore渠道的應(yīng)用無(wú)關(guān)。
在iOS8只是彈出一個(gè)窗問(wèn)你是否需要讓手機(jī)信任這個(gè)應(yīng)用,但是在iOS9卻直接禁止,如果真的想信任需要自己去手動(dòng)開(kāi)啟。類似于Mac系統(tǒng)從未知開(kāi)發(fā)者處下載的dmg直接打不開(kāi),然后要到系統(tǒng)偏好設(shè)置的安全性與隱私手動(dòng)打開(kāi)。 下圖展示左邊iOS8,右邊iOS9
?
用戶需要去 設(shè)置---》通用---》描述文件 里面自行添加信任。
這種問(wèn)題的處理方法也就兩種:1.提前周知暫時(shí)不要升級(jí)iOS9 ?2.大多是公司員工使用的企業(yè)級(jí)應(yīng)用,群發(fā)一個(gè)指導(dǎo)郵件。?
?
四、字體
iOS8中,字體是Helvetica,中文的字體有點(diǎn)類似于“華文細(xì)黑”。只是蘋(píng)果手機(jī)自帶渲染,所以看上去可能比普通的華文細(xì)黑要美觀。iOS9中,中文系統(tǒng)字體變?yōu)榱藢橹袊?guó)設(shè)計(jì)的“蘋(píng)方” 有點(diǎn)類似于一種word字體“幼圓”。字體有輕微的加粗效果,并且最關(guān)鍵的是字體間隙變大了!
所以很多原本寫(xiě)死了width的label可能會(huì)出現(xiàn)“...”的情況。
?iOS8
?iOS9 蛋疼
上面這兩張圖也可以直觀的看出同一個(gè)界面,同一個(gè)label的變化。
所以為了在界面顯示上不出錯(cuò),就算是固定長(zhǎng)度的文字也還是建議使用sizetofit 或者ios向上取整 ceilf() 或者提前計(jì)算
| 12 | CGSize size = [title sizeWithAttributes:@{NSFontAttributeName: [UIFont systemFontOfSize:14.0f]}];CGSize adjustedSize = CGSizeMake(ceilf(size.width), ceilf(size.height)); |
?
五、URL scheme
URL scheme一般使用的場(chǎng)景是應(yīng)用程序有分享或跳其他平臺(tái)授權(quán)的功能,分享或授權(quán)后再跳回來(lái)。
在iOS8并沒(méi)有做過(guò)多限制,但是iOS9需要將你要在外部調(diào)用的URL scheme列為白名單,才可以完成跳轉(zhuǎn)
如果iOS9沒(méi)做適配 會(huì)報(bào)如下錯(cuò)誤
| 1 | canOpenURL: failed for URL : "mqzone://qqapp" - error: "This app is not allowed to query for scheme mqzone" |
具體的解決方案也是要在info.plist中設(shè)置 LSApplicationQueriesSchemes 類型為數(shù)組,下面添加所有你用到的scheme
?
六、statusbar
這個(gè)還好只是報(bào)一個(gè)警告,如果就是不管他,也不會(huì)出現(xiàn)問(wèn)題。
| 1 | <Error>: CGContextSaveGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable. |
以前我們?yōu)榱四軌驅(qū)崟r(shí)的控制頂部statusbar的樣式,可能會(huì)在喜歡使用
| 12 | [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent][[UIApplication sharedApplication]setStatusBarHidden:YES]; |
但是這么做之前需要將 info.plist 里面加上View controller-based status bar appearance ?BOOL值設(shè)為NO,就是把控制器控制狀態(tài)欄的權(quán)限給禁了,用UIApplication來(lái)控制。但是這種做法在iOS9不建議使用了,建議我們使用吧那個(gè)BOOL值設(shè)為YES,然后用控制器的方法來(lái)管理狀態(tài)欄比如。
| 1234 | - (UIStatusBarStyle)preferredStatusBarStyle{????return UIStatusBarStyleLightContent;} |
點(diǎn)進(jìn)頭文件可以驗(yàn)證剛才說(shuō)法:
| 1 | @property(readwrite, nonatomic,getter=isStatusBarHidden) BOOL statusBarHidden NS_DEPRECATED_IOS(2_0, 9_0, "Use -[UIViewController prefersStatusBarHidden]"); |
?
七、didFinishLaunchingWithOptions
如果運(yùn)行的時(shí)候報(bào)下列錯(cuò)誤,那就是你的didFinishLaunchingWithOptions寫(xiě)的不對(duì)了
| 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結(jié)束了之后還沒(méi)有設(shè)置window的rootViewController。 也許是xcode7的編譯器本身就不支持。
解決的方法當(dāng)然就是先初始化個(gè)值,之后再賦值替換掉
| 12 | UIWindow *window = [[UIWindowalloc] initWithFrame:[UIScreenmainScreen].bounds];window.rootViewController = [[UIViewController alloc]init]; |
?
八、tableView
雖然現(xiàn)在的iOS9已經(jīng)推送正式版了,但是iOS9使用時(shí)還是會(huì)感覺(jué)到App比以前更加卡頓了,tableView拖動(dòng)時(shí)卡頓顯示的最為明顯。 并且之前遇到一個(gè)bug,原本好的項(xiàng)目用xcode7一編譯,tableView刷新出了問(wèn)題 ,[tableView reloadData]無(wú)效 有一行cell明明改變了但是刷新不出來(lái)。 感覺(jué)可能是這個(gè)方法和某種新加的特性沖突了,猜測(cè)可能是reloadData的操作被推遲到下一個(gè)RunLoop執(zhí)行最終失效。
解決的方法是,注釋[tableView reloadData],改用局部刷新,問(wèn)題居然就解決了。
| 1 | [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationNone]; |
?
九、NSLocalizableString(XCode7問(wèn)題)
如果你程序啟動(dòng)后出現(xiàn)主頁(yè)面一片空白,或是報(bào)了以下的棧調(diào)用錯(cuò)誤。那就是NSLocalizableString的死循環(huán)導(dǎo)致堆棧溢出了。
| 1234567891011121314151617 | #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] () |
這個(gè)的解決方法就是找到特定的頁(yè)面,然后將English 前面的勾勾上。
?
十、bundle identifier(Xcode7問(wèn)題)
如果你遇到了在本地編譯通過(guò),但是在CI上打包失敗。并且報(bào)的錯(cuò)誤是和bundle identifier相關(guān),那很有可能是你plist文件中寫(xiě)的bundle?identifier沒(méi)有起作用。
因?yàn)閤code7新增了此功能,在target下面的BuildSetting里面增加了Product Bundle identifier。蘋(píng)果之后的做法應(yīng)該是推薦在此處設(shè)置bundle identifier,此處的設(shè)置會(huì)比info.plist里面優(yōu)先讀取。
如果你的Bundle identifier一直沒(méi)變,可能不會(huì)發(fā)現(xiàn)此問(wèn)題。如果改變了,你在plist中修改是無(wú)效的。
另一個(gè)做法就是在ci打包的配置Execute shell上增加以下代碼
| 1 | "Set :CFBundleIdentifier com.XXX.XXX" "XXX/Supporting Files/XXX-Info.plist" |
?
十一、 ActionSheet
Actionsheet 在iOS8的時(shí)候改了一次版,當(dāng)時(shí)是和AlertView二合一,并且以AlertViewController作為載體,之后再present出來(lái),這在當(dāng)時(shí),蘋(píng)果應(yīng)該是想統(tǒng)一各個(gè)控件的展示方式,但是很多人可能并沒(méi)有在意因?yàn)橹苯觭how那個(gè)方法并沒(méi)有廢除,大家都覺(jué)得應(yīng)該是新舊都能用,再加上有的公司可能自己還做了一定擴(kuò)展,諸多原因?qū)е逻€是用的舊方法。
在iOS9上使用舊方法直接show,會(huì)出現(xiàn)左圖的問(wèn)題。如果用的是AlertViewController的方法則不會(huì)出現(xiàn)問(wèn)題(右圖)
? ??
我猜測(cè)可能是sheet的windowLevel比鍵盤低導(dǎo)致的。但是將優(yōu)先級(jí)設(shè)到10000,然后顯示在keyWindow上。
| 12 | sheet.window.windowLevel = 10000;[sheet showInView:[UIApplication sharedApplication].keyWindow]; |
然后沒(méi)有效果,然后又查了下stackoverflow 有個(gè)方法能取出優(yōu)先級(jí)最高的window
| 123 | UIWindow *topWindow = [[[UIApplication sharedApplication].windows sortedArrayUsingComparator:^NSComparisonResult(UIWindow *win1, UIWindow *win2) {????return win1.windowLevel - win2.windowLevel;}] lastObject]; |
試了下還是沒(méi)有效果。 應(yīng)該鍵盤的優(yōu)先級(jí)無(wú)論如何都是最高的, 想蓋在鍵盤上面的方法行不通。
當(dāng)然,如果更換的成本比較大,也并不是沒(méi)有辦法,直接設(shè)置彈sheet之前收回鍵盤就好了。
?
如果你不是在董鉑然博客園看到本文,請(qǐng)點(diǎn)擊查看原文。?
暫時(shí)遇到這些問(wèn)題,感覺(jué)iOS9的出現(xiàn)讓所有iOS開(kāi)發(fā)都是菊花一緊,預(yù)祝所有的iOS都能及時(shí)的做好適配改完bug,下個(gè)版本一上線,所有問(wèn)題都解決。
分類: 技術(shù)調(diào)研,探索分析標(biāo)簽: OC, iOS, iOS9, 適配, 新特性好文要頂關(guān)注我收藏該文董鉑然關(guān)注 - 7
粉絲 - 281 +加關(guān)注 7 ? 上一篇:iOS警告收錄及科學(xué)快速的消除方法
? 下一篇:將自己寫(xiě)的庫(kù)上傳到cocoapods(2015)
總結(jié)
以上是生活随笔為你收集整理的整理iOS9适配中出现的坑(图文)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: socket选项: SO_REUSEAD
- 下一篇: Python数据库使用-SQLite