微信 iOS9 適配總結

每年iOS升級,都會帶來一些坑,這次iOS9也不例外。本文總結了微信在適配iOS9上遇到的問題和解決方案。


一、iOS9問題彙總


1. 編譯問題(Bitcode)

大部分人升級到Xcode7後,首先遇到的問題是編譯不過,錯誤提示大致是

xxx 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.

這是因爲Xcode7默認啓用Bitcode,但是如果我們用到的第三方庫編譯時還沒啓用Bitcode,主工程就會編譯不過。

最簡單的解決辦法是先把Bitcode關掉:把Build settings - Build Options - Enable Bitcode 改爲NO。不過,這只是權宜之計。Bitcode是蘋果App Thinning的機制之一,可以減少安裝包的大小,等我們把所有庫都替換成支持Bitcode之後,主工程就可以啓用Bitcode了。


2、HTTP請求失敗

解決了編譯問題後,程序跑起來了,卻發現很多網絡請求失敗。這是因爲iOS9默認不支持HTTP請求,需要改用更安全的HTTPS(默認用TLS 1.2)。

但事實上,有些地方用HTTP比HTTPS更適合,而且把服務端升級到TLS 1.2也不是一時半會能夠搞定的。幸好蘋果還提供了配置,使得所有安全性更低的網絡請求也能使用,解決方案就是在info.plist裏面增加以下配置:

<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>

如果複雜一些,還可以指定白名單域名,聲明所支持TLS的最低版本,這裏就不再詳細描述了。


另外需要注意的是,即使寫了上述配置,在HTTPS頁面中,HTTP的javascript或css不會被加載,因爲蘋果認爲這降低了頁面的安全性。


3、canOpenUrl限制

canOpenUrl可以用來判斷用戶是否安裝了某個APP。也許是出於用戶隱私的考慮,iOS9上對canOpenUrl做了限制,最多隻能對50個scheme做判斷。

如果是用Xcode7編譯,需要在plist裏面聲明這些scheme,沒有聲明的會直接返回NO:

<key>LSApplicationQueriesSchemes</key>
<array>
<string>weixin</string>
<string>wechat</string>
</array>

如果是用Xcode6編譯,系統會在用戶手機上記住APP每次調用canOpenUrl的scheme,如果累計達到50種,剩下的其它調用,也會直接返回NO。所以在iOS9beta剛出來的時候,有些用戶無法從微信跳轉到第三方app,就是因爲已經達到了限制數量,系統直接返回NO,程序以爲用戶沒有安裝該APP,就沒有去跳轉。


解決辦法是加白名單,並且儘量減少不必要的canOpenUrl調用,以免超過50個名額的限制。

例如,openUrl函數是不受限制的(在iOS9的某beta版上,openUrl也受同樣限制,但跟蘋果溝通後確認是iOS的bug,後面的版本也已經更正過來了),所以對於

if (canOpenUrl(scheme)) then openUrl(scheme);
else xxx;

這種只需要改寫成

if (!openUrl(scheme)) then xxx;

就不用佔用白名單了。


4、systemName

[[UIDevice currentDevice] systemName]在過去版本中一直返回"iPhone OS",但在iOS9.1 beta中,這個函數返回值變成了"iOS"。

這個看似不起眼的改動,卻使得微信出現了很多問題。刷了9.1beta的用戶會發現,所有的公衆號消息、小視頻、紅包等消息都無法查看,登陸驗證也會失敗。這是因爲後臺依賴systemName來判斷設備類型,未知類型會使得後臺以爲該設備不支持某些功能,導致該功能失效。

解決方法是後臺修改判斷條件,並吸取教訓支持可配置,上線後解決了這個問題。

然而,在iOS9.1正式版上,蘋果又把systemName改回"iPhone OS"了。或許蘋果也發現這個小小的改動會引起一些致命問題,所以又改了回來。


5、preferredLanguages

[NSLocale preferredLanguages]會返回用戶的首選語言。在之前的版本,系統用"zh-Hans"來表示簡體中文,這個常量在iOS9.0beta上也是如此。然而到了iOS9.0正式版,蘋果突然在後面加了國家碼後綴,變成了"zh-Hans-CN"。但是,對於臺灣繁體中文,卻沒有變化,依然是"zh-TW"。

這個變動導致部分用戶升級到iOS9,微信語言變成了英文。這是因爲程序在用戶首選語言中沒匹配到簡體中文的選項。

目前我們解決辦法是改用前綴匹配。


6、API更新

iOS9照例淘汰了一些舊接口,其中有一些舊接口雖然還能用,但或多或少都會有些問題:


6.1 AddressBookUI.framework在iOS9上已經被淘汰,需要改用ContactsUI.framework

舊接口還能夠讀取通訊錄,但是添加信息到通訊錄時,系統界面會卡住。


6.2 UIAlertView需要改成UIAlertController

舊接口還能夠使用,只是在有鍵盤的情況下彈UIAlertView,可能會有鍵盤閃現等體驗問題。


6.3 UIPopoverController需要改用普通的UIViewController,設置modalPresentationStyle=UIModalPresentationPopover,然後present出來

舊接口也能夠使用,但在iPad分屏下會有問題。


7、windowLevel問題

如下圖所示,當鍵盤已經彈起的時候,再顯示我們自己寫的確認窗口等window,會發現window被鍵盤擋住了。


這是因爲iOS9下系統鍵盤的windowLevel是很高的,達到10^7。而且進一步發現,這個值是系統允許的最大值。如果把某個window的windowLevel改成比10^7大的值,系統只會設爲10^7。

解決這個問題有兩種方法:

一個是把我們自己window的level調大,同樣設爲10^7,因爲比系統鍵盤晚出現,所以還是能夠把系統鍵盤蓋住。這種方法的缺點是使得window的層次結構不好管理,且依賴於系統鍵盤的level。而且window上也無法再顯示UIAlertView等系統窗口了。

另一種方法是在顯示window時先調用[mainWindow endEditing:YES],把主window的鍵盤收起來,然後再顯示window。這種方法的缺點是,有些場景下用戶是正在輸入的,收起鍵盤對用戶的體驗不好。

兩種方法各有優缺點,可以根據使用場景來選擇。


8. 啓動crash(window.rootViewController問題)

crash信息爲:Application windows are expected to have a root view controller at the end of application launch

原因是啓動完的時候,如果現有的window沒有rootViewController,就會crash。

解決辦法就是按要求設置rootViewController。

注:啓動完後再生成的window,可以不設rootViewController,但還是建議以後所有window都要設。


二、iPad分屏


1、如何啓用iPad分屏

a. 用Xcode7 iOS9 SDK編譯

b. 用Launch StoryBoard做啓動界面

c. 支持所有的旋轉方向


需要注意的是,支持分屏後,iPad上所有界面都需要支持轉屏。如果以前通過supportedInterfaceOrientations等函數來限制某些界面在iPad上不能轉屏,在啓用分屏後這個限制將失效。


如果不支持分屏,需要在項目設置中的General - Deployment Info中勾選Requires full screen


2、如何適配iPad分屏

分屏和轉屏本質上都是改變了屏幕的尺寸。正常來說,如果界面適配了iPad轉屏(不管是用哪種方式,例如AutoLayout,或者AutoResizing,或者是在viewDidLayoutSubviews裏面重新排版,等等),那在iPad分屏下也能夠正常顯示。(除了一些特殊情況,例如hardcode了屏幕尺寸等,見後面第3點。)

如果界面在不同尺寸的屏幕下有不同的排版設計,官方的建議是根據系統回調在Regular模式和Compact模式之間切換。微信因爲是使用了配置文件來處理不同設備的排版差異的,所以根據自己的實際情況,採用以下原則:在320屏幕下按照iPhone5的排版;438屏幕下按照iPhone6的排版,其它分屏下按照iPad的排版。


3、分屏後的幾個問題

3.1 有了分屏後,APP當前屏幕的大小不能再用[UIScreen mainScreen].bound來獲取了,這個取到的是整個設備的屏幕大小,不是分屏後的屏幕大小。

解決辦法是,啓動時初始化window,不需要initWithFrame,直接用init就可以了。系統知道當前屏幕的大小,會幫我們正確地設置frame。然後取這個frame就能拿到實際屏幕大小了。


3.2 以前適配iPad轉屏時,有些地方會使用willRotateToInterfaceOrientation等轉屏回調來處理屏幕尺寸變化。從iOS8開始,系統新增了viewWillTransitionToSize:withTransitionCoordinator回調來代替它。新的回調可以用來處理轉屏和分屏引起的屏幕尺寸變化。


3.3 分屏狀態下,系統的視頻錄製功能不可用。如果某個功能用到了視頻錄製功能,建議像系統照相機一樣,在分屏時給用戶提示一下。


3.4 避免hardcode。要注意iPad的屏幕不再是1024*768,而且在運行中屏幕的尺寸是會隨時變化的(分屏或轉屏時),所以如果以前有些代碼做了hardcode,會導致分屏後有bug。


三、總結

本文總結了微信在適配iOS9中遇到的常見問題,相信iOS9還有其它深坑有待挖掘,歡迎大家補充。



原文鏈接:http://mp.weixin.qq.com/s?__biz=MzAwNDY1ODY2OQ==&mid=400069917&idx=1&sn=ac651a2ba788980fb6730dc0c322293c&3rd=MzA3MDU4NTYzMw==&scene=6#rd

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章