每年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还有其它深坑有待挖掘,欢迎大家补充。

最新文章

  1. 新浪微博AppKey大集合(share)
  2. 退役了退役了-AJAX
  3. iOS开发-简单解析JSON数据
  4. IplImage 与 QImage 相互转换
  5. 什么是BI(Business Intelligence)【转】
  6. Android 视频投射之NanoHTTPD
  7. hive 调用java的函数和科学记数法转换
  8. Javascript如何判断一个变量是数字类型?
  9. JS 乱记
  10. VS IDE环境下,windows GUI(Qt MFC,win32)使用控制台实时打印调试信息
  11. Iframe和父窗口互调方法的集合
  12. Linux的起源、特点和版本号
  13. Word报告自动生成(例如 导出数据库结构)
  14. 新的编辑工具IDE
  15. 如何优化 ThreadPoolExecutor
  16. 记录4-Ubuntu 16.04用gparted调整分区
  17. vc++基础班[27]---实现一个简单的任务管理器
  18. 【Zookeeper系列】zookeeper面试题(转)
  19. a链接的onclick与js中的return false
  20. Plant(&#119862;&#119900;&#119889;&#119890;&#119865;&#119900;&#119903;&#119888;&#119890;&#119904; − 185&#119860;)

热门文章

  1. 关于c语言中的字符串问题
  2. Hive进阶_Hive的子查询
  3. shell 获得调用的python脚本的print值和错误log
  4. c++笔记3
  5. (转)nginx域名访问的白名单配置梳理
  6. DNS学习
  7. rabbitmq 不发送ack消息如何处理: RabbitMQ 消息确认以及消息消费方处理消息时候抛出了异常以
  8. 记录下这周的mysql调优工作
  9. dubbo服务降级(2)
  10. spring data jpa 简单使用