低代码到底是不是行业毒瘤?一线大厂怎么做的?戳此了解>>> 了解详情
写点什么

微信 iOS 9 适配总结

2015 年 11 月 09 日

编者按:微信作为国内最大的移动社交软件和开放平台,其技术也一直为外人所好奇。InfoQ 特地与微信团队合作推出系列专栏,介绍支撑亿级并发背后的技术。

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

2015 年 11 月 09 日 00:5010105

评论

发布
暂无评论
发现更多内容

架构师训练营第二周命题作业

成长者

极客大学架构师训练营

[架构师训练营第1期]第二周命题作业

猫切切切切切

极客大学架构师训练营

做好分库分表其实很难之一

架构师修行之路

微服务 分库分表

数字与能源,交织成新基建的摩比斯环

脑极体

字节3-2专家3年心血终成IT运维之道PDF(IT运维精髓)

周老师

Java 编程 程序员 架构 面试

架构训练营 -week2- 学习总结

于成龙

面向对象 架构训练营

八、给小白看的第一篇Python基础教程

刘润森

Python

第二周学习总结

追风

极客大学架构师训练营

学生成绩管理系统案例

C语言与CPP编程

编程语言 C语言 编译器、程序语言、CPU

第二课框架设计课后作业

Geek_michael

架构师训练营 Week2 作业

lggl

极客大学架构师训练营 作业

三、新手Jupyter不会用,我十招教你盘她

刘润森

Python

五、开始Github和码云之旅,新手如何上路

刘润森

Python

九种查找算法

C语言与CPP编程

面试 算法 编程语言 C语言 编译器、程序语言、CPU

前言、Python是真的火,还是炒得火?来看看它的前世和发展

刘润森

Python

架构师训练营第一期 - week2 - 命题作业

谭明华

极客大学架构师训练营

架构师训练营第 1 期 - 第二周 - 作业提交

Todd-Lee

架构师 极客大学架构师训练营

四、学编程语言前,不了解Git,怎么入坑

刘润森

Python

字符串操作的全面总结

C语言与CPP编程

编程语言 C语言 编译器、程序语言、CPU 字符串

架构1期第二周作业

FG佳

架构师训练营 1 期 -- 第二周作业

曾彪彪

极客大学架构师训练营

一、搭建Python环境和安装Pycharm

刘润森

Python

六、乘胜追击,将剩下的Git知识点搞定

刘润森

七、连Pycharm都不知道怎么用,学什么Python

刘润森

Python

高并发下如何缩短响应时间

架构师修行之路

微服务 高并发优化

「架构师训练营第1期」第二周作业

张国荣

极客大学架构师训练营

五种简单高效的拆分用户故事的方法

Bruce Talk

敏捷 Agile 用户故事 User Story Product Owner

二、搭建Jupyter Notebook环境

刘润森

Python

C语言C++中assert的用法

C语言与CPP编程

程序员 编程语言 C语言

代码防御性编程的十条技巧

C语言与CPP编程

程序员 编程语言 C语言 编译器、程序语言、CPU

十、给小白看的第三篇Python基础教程

刘润森

Python

2021 ThoughtWorks 技术雷达峰会

2021 ThoughtWorks 技术雷达峰会

微信iOS 9适配总结-InfoQ