http://www.mamicode.com/info-detail-1158873.htmljavascript
每一年iOS升级,都会带来一些坑,此次iOS9也不例外。本文总结了微信在适配iOS9上遇到的问题和解决方案。css
1、iOS9问题汇总html
1. 编译问题(Bitcode)java
大部分人升级到Xcode7后,首先遇到的问题是编译不过,错误提示大体是windows
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了。微信
二、HTTP请求失败网络
解决了编译问题后,程序跑起来了,却发现不少网络请求失败。这是由于iOS9默认不支持HTTP请求,须要改用更安全的HTTPS(默认用TLS 1.2)。app
但事实上,有些地方用HTTP比HTTPS更适合,并且把服务端升级到TLS 1.2也不是一时半会可以搞定的。幸亏苹果还提供了配置,使得全部安全性更低的网络请求也能使用,解决方案就是在info.plist里面增长如下配置:函数
<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict>
若是复杂一些,还能够指定白名单域名,声明所支持TLS的最低版本,这里就再也不详细描述了。
另外须要注意的是,即便写了上述配置,在HTTPS页面中,HTTP的javascript或css不会被加载,由于苹果认为这下降了页面的安全性。
三、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;
就不用占用白名单了。
四、systemName
[[UIDevice currentDevice] systemName]在过去版本中一直返回"iPhone OS",但在iOS9.1 beta中,这个函数返回值变成了"iOS"。
这个看似不起眼的改动,却使得微信出现了不少问题。刷了9.1beta的用户会发现,全部的公众号消息、小视频、红包等消息都没法查看,登录验证也会失败。这是由于后台依赖systemName来判断设备类型,未知类型会使得后台觉得该设备不支持某些功能,致使该功能失效。
解决方法是后台修改判断条件,并吸收教训支持可配置,上线后解决了这个问题。
然而,在iOS9.1正式版上,苹果又把systemName改回"iPhone OS"了。或许苹果也发现这个小小的改动会引发一些致命问题,因此又改了回来。
五、preferredLanguages
[NSLocale preferredLanguages]会返回用户的首选语言。在以前的版本,系统用"zh-Hans"来表示简体中文,这个常量在iOS9.0beta上也是如此。然而到了iOS9.0正式版,苹果忽然在后面加了国家码后缀,变成了"zh-Hans-CN"。可是,对于台湾繁体中文,却没有变化,依然是"zh-TW"。
这个变更致使部分用户升级到iOS9,微信语言变成了英文。这是由于程序在用户首选语言中没匹配到简体中文的选项。
目前咱们解决办法是改用前缀匹配。
六、API更新
iOS9照例淘汰了一些旧接口,其中有一些旧接口虽然还能用,但或多或少都会有些问题:
6.1 AddressBookUI.framework在iOS9上已经被淘汰,须要改用ContactsUI.framework
旧接口还可以读取通信录,可是添加信息到通信录时,系统界面会卡住。
6.2 UIAlertView须要改为UIAlertController
旧接口还可以使用,只是在有键盘的状况下弹UIAlertView,可能会有键盘闪现等体验问题。
6.3 UIPopoverController须要改用普通的UIViewController,设置modalPresentationStyle=UIModalPresentationPopover,而后present出来
旧接口也可以使用,但在iPad分屏下会有问题。
七、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都要设。
2、iPad分屏
一、如何启用iPad分屏
a. 用Xcode7 iOS9 SDK编译
b. 用Launch StoryBoard作启动界面
c. 支持全部的旋转方向
须要注意的是,支持分屏后,iPad上全部界面都须要支持转屏。若是之前经过supportedInterfaceOrientations等函数来限制某些界面在iPad上不能转屏,在启用分屏后这个限制将失效。
若是不支持分屏,须要在项目设置中的General - Deployment Info中勾选Requires full screen
二、如何适配iPad分屏
分屏和转屏本质上都是改变了屏幕的尺寸。正常来讲,若是界面适配了iPad转屏(不论是用哪一种方式,例如AutoLayout,或者AutoResizing,或者是在viewDidLayoutSubviews里面从新排版,等等),那在iPad分屏下也可以正常显示。(除了一些特殊状况,例如hardcode了屏幕尺寸等,见后面第3点。)
若是界面在不一样尺寸的屏幕下有不一样的排版设计,官方的建议是根据系统回调在Regular模式和Compact模式之间切换。微信由于是使用了配置文件来处理不一样设备的排版差别的,因此根据本身的实际状况,采用如下原则:在320屏幕下按照iPhone5的排版;438屏幕下按照iPhone6的排版,其它分屏下按照iPad的排版。
三、分屏后的几个问题
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。
3、总结
本文总结了微信在适配iOS9中遇到的常见问题,相信iOS9还有其它深坑有待挖掘,欢迎你们补充。