请选择 进入手机版 | 继续访问电脑版

默认
打赏 发表评论 5
全面总结iOS版微信升级iOS9遇到的各种“坑”

本文由微信开发团队人员编写,转自 WeMobileDev,感谢。


前言


随着iOS系统版本的不断升级,APP几乎无一例外的需要同步进行适配和升级。每次iOS系统升级最开心的是用户,而最悲催的莫过于iOS开发人员——拿到新系统后第一时间要做的就是不断的适配和修改因系统的不兼容而带来的bug,那些曾经的“坑”真是罄竹难书,而本次iOS9的升级也没有例外。

本文将总结本次微信客户端在适配iOS9上遇到的问题和解决方案。

各种基础适配问题及解决方案


1Bitcode新特性导致的编译问题


大部分人升级到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了。

2iOS9中升级TLS1.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不会被加载,因为苹果认为这降低了页面的安全性。

3canOpenUrl限制问题


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;

就不用占用白名单了。

4iOS beta版和正式版中systemName不一致导致的问题


[[UIDevice currentDevice] systemName]在过去版本中一直返回"iPhone OS",但在iOS9.1 beta中,这个函数返回值变成了"iOS"。

这个看似不起眼的改动,却使得微信出现了很多问题。刷了9.1beta的用户会发现,所有的公众号消息、小视频、红包等消息都无法查看,登陆验证也会失败。这是因为后台依赖systemName来判断设备类型,未知类型会使得后台以为该设备不支持某些功能,导致该功能失效。

解决方法是后台修改判断条件,并吸取教训支持可配置,上线后解决了这个问题。然而,在iOS9.1正式版上,苹果又把systemName改回"iPhone OS"了。或许苹果也发现这个小小的改动会引起一些致命问题,所以又改了回来。

5iOS9变更了简体中文国家码导致的问题


[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分屏下会有问题。

7windowLevel问题


如下图所示,当键盘已经弹起的时候,再显示我们自己写的确认窗口等window,会发现window被键盘挡住了:

微信windowLevel问题.jpg

这是因为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启动即崩溃(未设置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分屏后的几个问题


- 问题描述:有了分屏后,APP当前屏幕的大小不能再用[UIScreen mainScreen].bound来获取了,这个取到的是整个设备的屏幕大小,不是分屏后的屏幕大小。
- 解决办法:启动时初始化window,不需要initWithFrame,直接用init就可以了。系统知道当前屏幕的大小,会帮我们正确地设置frame。然后取这个frame就能拿到实际屏幕大小了。

- 问题描述:willRotateToInterfaceOrientation与viewWillTransitionToSize:withTransitionCoordinator导致的问题。
- 解决办法:以前适配iPad转屏时,有些地方会使用willRotateToInterfaceOrientation等转屏回调来处理屏幕尺寸变化。从iOS8开始,系统新增了viewWillTransitionToSize:withTransitionCoordinator回调来代替它。新的回调可以用来处理转屏和分屏引起的屏幕尺寸变化。

- 问题描述:分屏状态下,系统的视频录制功能不可用。
- 解决办法:如果某个功能用到了视频录制功能,建议像系统照相机一样,在分屏时给用户提示一下。

- 问题描述:hardcode带来的问题。
- 解决办法:避免hardcode。要注意iPad的屏幕不再是1024*768,而且在运行中屏幕的尺寸是会随时变化的(分屏或转屏时),所以如果以前有些代码做了hardcode,会导致分屏后有bug。

全站即时通讯技术资料分类


[1] 网络编程基础资料:
TCP/IP详解 - 第11章·UDP:用户数据报协议
TCP/IP详解 - 第17章·TCP:传输控制协议
TCP/IP详解 - 第18章·TCP连接的建立与终止
TCP/IP详解 - 第21章·TCP的超时与重传
理论经典:TCP协议的3次握手与4次挥手过程详解
理论联系实际:Wireshark抓包分析TCP 3次握手、4次挥手过程
计算机网络通讯协议关系图(中文珍藏版)
NAT详解:基本原理、穿越技术(P2P打洞)、端口老化等
UDP中一个包的大小最大能多大?
Java新一代网络编程模型AIO原理及Linux系统AIO介绍
NIO框架入门(三):iOS与MINA2、Netty4的跨平台UDP双向通信实战
NIO框架入门(四):Android与MINA2、Netty4的跨平台UDP双向通信实战
>> 更多同类文章 ……

[2] 有关IM/推送的通信格式、协议的选择:
为什么QQ用的是UDP协议而不是TCP协议?
移动端即时通讯协议选择:UDP还是TCP?
如何选择即时通讯应用的数据传输格式
强列建议将Protobuf作为你的即时通讯应用数据传输格式
移动端IM开发需要面对的技术问题(含通信协议选择)
简述移动端IM开发的那些坑:架构设计、通信协议和客户端
理论联系实际:一套典型的IM通信协议设计详解
58到家实时消息系统的协议设计等技术实践分享
>> 更多同类文章 ……

[3] 有关IM/推送的心跳保活处理:
Android进程保活详解:一篇文章解决你的所有疑问
Android端消息推送总结:实现原理、心跳保活、遇到的问题等
为何基于TCP协议的移动端IM仍然需要心跳保活机制?
微信团队原创分享:Android版微信后台保活实战分享(进程保活篇)
微信团队原创分享:Android版微信后台保活实战分享(网络保活篇)
移动端IM实践:实现Android版微信的智能心跳机制
移动端IM实践:WhatsApp、Line、微信的心跳策略分析
>> 更多同类文章 ……

[4] 有关WEB端即时通讯开发:
新手入门贴:史上最全Web端即时通讯技术原理详解
Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE
SSE技术详解:一种全新的HTML5服务器推送事件技术
Comet技术详解:基于HTTP长连接的Web端实时通信技术
WebSocket详解(一):初步认识WebSocket技术
socket.io实现消息推送的一点实践及思路
>> 更多同类文章 ……

[5] 有关IM架构设计:
浅谈IM系统的架构设计
简述移动端IM开发的那些坑:架构设计、通信协议和客户端
一套原创分布式即时通讯(IM)系统理论架构方案
从零到卓越:京东客服即时通讯系统的技术架构演进历程
蘑菇街即时通讯/IM服务器开发之架构选择
腾讯QQ1.4亿在线用户的技术挑战和架构演进之路PPT
微信技术总监谈架构:微信之道——大道至简(演讲全文)
如何解读《微信技术总监谈架构:微信之道——大道至简》
快速裂变:见证微信强大后台架构从0到1的演进历程(一)
17年的实践:腾讯海量产品的技术方法论
>> 更多同类文章 ……

[6] 有关IM安全的文章:
即时通讯安全篇(一):正确地理解和使用Android端加密算法
即时通讯安全篇(二):探讨组合加密算法在IM中的应用
即时通讯安全篇(三):常用加解密算法与通讯安全讲解
即时通讯安全篇(四):实例分析Android中密钥硬编码的风险
传输层安全协议SSL/TLS的Java平台实现简介和Demo演示
理论联系实际:一套典型的IM通信协议设计详解(含安全层设计)
微信新一代通信安全解决方案:基于TLS1.3的MMTLS详解
来自阿里OpenIM:打造安全可靠即时通讯服务的技术实践分享
>> 更多同类文章 ……

[7] 有关实时音视频开发:
即时通讯音视频开发(一):视频编解码之理论概述
即时通讯音视频开发(二):视频编解码之数字视频介绍
即时通讯音视频开发(三):视频编解码之编码基础
即时通讯音视频开发(四):视频编解码之预测技术介绍
即时通讯音视频开发(五):认识主流视频编码技术H.264
即时通讯音视频开发(六):如何开始音频编解码技术的学习
即时通讯音视频开发(七):音频基础及编码原理入门
即时通讯音视频开发(八):常见的实时语音通讯编码标准
即时通讯音视频开发(九):实时语音通讯的回音及回音消除概述
即时通讯音视频开发(十):实时语音通讯的回音消除技术详解
即时通讯音视频开发(十一):实时语音通讯丢包补偿技术详解
即时通讯音视频开发(十二):多人实时音视频聊天架构探讨
即时通讯音视频开发(十三):实时视频编码H.264的特点与优势
即时通讯音视频开发(十四):实时音视频数据传输协议介绍
即时通讯音视频开发(十五):聊聊P2P与实时音视频的应用情况
即时通讯音视频开发(十六):移动端实时音视频开发的几个建议
即时通讯音视频开发(十七):视频编码H.264、V8的前世今生
简述开源实时音视频技术WebRTC的优缺点
良心分享:WebRTC 零基础开发者教程(中文)
>> 更多同类文章 ……

[8] IM开发综合文章:
移动端IM开发需要面对的技术问题
开发IM是自己设计协议用字节流好还是字符流好?
请问有人知道语音留言聊天的主流实现方式吗?
IM系统中如何保证消息的可靠投递(即QoS机制)
谈谈移动端 IM 开发中登录请求的优化
完全自已开发的IM该如何设计“失败重试”机制?
微信对网络影响的技术试验及分析(论文全文)
即时通讯系统的原理、技术和应用(技术论文)
开源IM工程“蘑菇街TeamTalk”的现状:一场有始无终的开源秀
>> 更多同类文章 ……

[9] 开源移动端IM技术框架资料:
开源移动端IM技术框架MobileIMSDK:快速入门
开源移动端IM技术框架MobileIMSDK:常见问题解答
开源移动端IM技术框架MobileIMSDK:压力测试报告
开源移动端IM技术框架MobileIMSDK:Android版Demo使用帮助
开源移动端IM技术框架MobileIMSDK:Java版Demo使用帮助
开源移动端IM技术框架MobileIMSDK:iOS版Demo使用帮助
开源移动端IM技术框架MobileIMSDK:Android客户端开发指南
开源移动端IM技术框架MobileIMSDK:Java客户端开发指南
开源移动端IM技术框架MobileIMSDK:iOS客户端开发指南
开源移动端IM技术框架MobileIMSDK:Server端开发指南
>> 更多同类文章 ……

[10] 有关推送技术的文章:
iOS的推送服务APNs详解:设计思路、技术原理及缺陷等
Android端消息推送总结:实现原理、心跳保活、遇到的问题等
扫盲贴:认识MQTT通信协议
一个基于MQTT通信协议的完整Android推送Demo
求教android消息推送:GCM、XMPP、MQTT三种方案的优劣
移动端实时消息推送技术浅析
扫盲贴:浅谈iOS和Android后台实时消息推送的原理和区别
绝对干货:基于Netty实现海量接入的推送服务技术要点
移动端IM实践:谷歌消息推送服务(GCM)研究(来自微信)
为何微信、QQ这样的IM工具不使用GCM服务推送消息?
>> 更多同类文章 ……

[11] 更多即时通讯技术好文分类:
http://www.52im.net/forum.php?mod=collection&op=all

附录:有关QQ、微信的文章汇总


[1] 有关QQ、微信的技术文章:
微信后台团队:微信后台异步消息队列的优化升级实践分享
微信团队原创分享:微信客户端SQLite数据库损坏修复实践
腾讯原创分享(一):如何大幅提升移动网络下手机QQ的图片传输速度和成功率
腾讯原创分享(二):如何大幅压缩移动网络下APP的流量消耗(下篇)
腾讯原创分享(二):如何大幅压缩移动网络下APP的流量消耗(上篇)
微信Mars:微信内部正在使用的网络层封装库,即将开源
如约而至:微信自用的移动端IM网络层跨平台组件库Mars已正式开源
开源libco库:单机千万连接、支撑微信8亿用户的后台框架基石 [源码下载]
微信新一代通信安全解决方案:基于TLS1.3的MMTLS详解
微信团队原创分享:Android版微信后台保活实战分享(进程保活篇)
微信团队原创分享:Android版微信后台保活实战分享(网络保活篇)
Android版微信从300KB到30MB的技术演进(PPT讲稿) [附件下载]
微信团队原创分享:Android版微信从300KB到30MB的技术演进
微信技术总监谈架构:微信之道——大道至简(演讲全文)
微信技术总监谈架构:微信之道——大道至简(PPT讲稿) [附件下载]
如何解读《微信技术总监谈架构:微信之道——大道至简》
微信海量用户背后的后台系统存储架构(视频+PPT) [附件下载]
微信异步化改造实践:8亿月活、单机千万连接背后的后台解决方案
微信朋友圈海量技术之道PPT [附件下载]
微信对网络影响的技术试验及分析(论文全文)
一份微信后台技术架构的总结性笔记
架构之道:3个程序员成就微信朋友圈日均10亿发布量[有视频]
快速裂变:见证微信强大后台架构从0到1的演进历程(一)
快速裂变:见证微信强大后台架构从0到1的演进历程(二)
微信团队原创分享:Android内存泄漏监控和优化技巧总结
全面总结iOS版微信升级iOS9遇到的各种“坑”
微信团队原创资源混淆工具:让你的APK立减1M
微信团队原创Android资源混淆工具:AndResGuard [有源码]
Android版微信安装包“减肥”实战记录
iOS版微信安装包“减肥”实战记录
移动端IM实践:iOS版微信界面卡顿监测方案
微信“红包照片”背后的技术难题
移动端IM实践:iOS版微信小视频功能技术方案实录
移动端IM实践:Android版微信如何大幅提升交互性能(一)
移动端IM实践:Android版微信如何大幅提升交互性能(二)
移动端IM实践:实现Android版微信的智能心跳机制
移动端IM实践:WhatsApp、Line、微信的心跳策略分析
移动端IM实践:谷歌消息推送服务(GCM)研究(来自微信)
移动端IM实践:iOS版微信的多设备字体适配方案探讨
>> 更多同类文章 ……

[2] 有关QQ、微信的技术故事:
技术往事:创业初期的腾讯——16年前的冬天,谁动了马化腾的代码
技术往事:史上最全QQ图标变迁过程,追寻IM巨人的演进历史
开发往事:深度讲述2010到2015,微信一路风雨的背后
开发往事:微信千年不变的那张闪屏图片的由来
开发往事:记录微信3.0版背后的故事(距微信1.0发布9个月时)
一个微信实习生自述:我眼中的微信开发团队
>> 更多同类文章 ……

即时通讯网 - 即时通讯开发者社区! 来源: - 即时通讯开发者社区!

上一篇:微信团队原创资源混淆工具:让你的APK立减1M下一篇:微信团队原创分享:Android内存泄漏监控和优化技巧总结

本帖已收录至以下技术专辑

推荐方案
评论 5
iOS每次升级带来的兼容性问题真是相当恶心,然并卵,他就是这么强势。。。
签名: 心烦意乱
那个https强制要求真是想骂娘啊
签名: 好想把妹!
不是iOS开发人员深表同情并轻轻的飘过。。。

签名: 好久没来了,签个到
从第4和第5点来看,ios团队真有这么草率?真是不感相信~~~
长知识了
打赏楼主 ×
使用微信打赏! 使用支付宝打赏!

返回顶部