【团队分享】iOS8.3给发图带来的坑,怎样迅速填平?
2015-05-30 17:12
393 查看
向华,手机QQ项目团队,高级移动开发工程师,座右铭:Be The Best!
--------------------------------------------------------------------------
4月9号,苹果开始向iOS用户推送最新系统版本iOS8.3的升级。手机QQ团队第一时间进行系统升级的兼容性验证,发现在图片选择器界面切换标清图和原图时必现闪退现象。同时,在微博、论坛和support平台等渠道均有收到大量用户反馈此问题。
于是,我们迅速在厂内的崩溃统计分析平台(
小编注: 即Bugly平台)查找相应崩溃问题的堆栈信息进行分析。
初步分析发现崩溃问题定位在
UIView addSubview的调用,并有明确的错误信息:
<span style="font-size:12px;">Terminating app due to uncaught exception 'UIApplicationInvalidInterfaceOrientation', reason: 'Supported orientations has no common orientation with the application, and [QQMarkActionSheetController_FixPos shouldAutorotate] is returning YES'</span>
我们进行了真机联调测试,验证崩溃问题必现场景同崩溃分析平台记录的一致。
再分析崩溃信息的详情,可以明确崩溃问题是由于
QQMarkActionSheetController_FixPos的方向和
application的方向不一致导致的。
于是,按照如下方法修复此问题:
1. 查找源码定位
QQMarkActionSheetController_FixPos继承自
UIAlertController
2. 重写
shouldAutorotate方法,返回值设为NO
重新编译调式验证,崩溃问题果然解决。
但正所谓“福无双至,祸不单行”,我们继续深入一些隐蔽场景测试,又发现两个必现崩溃的场景:
· 编辑图片后选择取消
· 关闭Wi-Fi后发送短视频
分析对比后,发现这两个场景有一个共同的业务逻辑,即是弹出
UIAlertView进行消息提示,且崩溃的位置和错误的信息和前面提到的崩溃问题很相似:
<span style="font-size:12px;">Supported orientations has no common orientation with the application, and [_UIAlertShimPresentingViewController shouldAutorotate] is returning YES</span>
也是由于
_UIAlertShimPresentingViewController的方向和
application的方向不一致导致应用崩溃。
注意,此时,我们就不能跟前面提到的崩溃问题采用同样的方法进行修复了!
因为,
_UIAlertShimPresentingViewController是系统内部的类,我们没法重写其
shouldAutorotate方法。
所以,我们开始怀疑是否在iOS8.3系统中,是不是所有调用
UIAlertView的地方都会发生崩溃?
但在选择了几个调用
UIAlertView的界面进行验证后,发现并没有崩溃发生。这种情况让我们很是困惑,在一番探索后,我们把焦点转移到项目中二次封装的
SimpleAlertView上,尝试把出现崩溃场景的
UIAlertView换成
SimpleAlertView,联调测试验证后发现崩溃问题没有再出现。
于是,我们得到一个解决此类崩溃问题的方法:
将工程中所有调用
UIAlertView执行UI提示的逻辑全部替换为调用
SimpleAlertView执行,当然,还需根据不同的场景修改适配UI样式和交互表现。
但古人有曰,三思而后行。
我们在工程中搜索
UIAlertView的调用,发现竟有500+的调用,分别分布在300+的文件中,如果替换的话,其潜在风险和工作量都要仔细考量,而且还需针对不同场景修改UI样式和交互表现,不可取!
所以,我们否决了此解决方法,继续分析问题并探索其他的解决方法。
在前面的验证过程中,我们发现并非所有出现
UIAlertView的界面都发生了崩溃,而是只有三个场景出现此类问题,而且都和图片选择器有关,于是把焦点又转移到图片选择器相关的逻辑,并进行了一系列的检查和验证:
1. Review代码,确认图片选择器里面的
shouldAutorotate方法返回值确实为NO
2. 测试在3G环境下拍摄短视频发送,弹出流量提示框,无崩溃发生
3. 从图片选择器界面发送短视频,弹出流量提示框时,发生崩溃
由此,我们断定问题在图片选择器的相关处理中。
于是又搜索了其他场景使用
UIAlertView但没有崩溃的代码,对比发现二者的
supportedInterfaceOrientations方法有一些差异:
· 图片选择器的视图控制器里面
supportedInterfaceOrientations方法返回值为
UIInterfaceOrientationPortrait
(NSUInteger) supportedInterfaceOrientations { return UIInterfaceOrientationPortrait; }
· 其他场景的
supportedInterfaceOrientations方法返回值为
UIInterfaceOrientationMaskPortrait
(NSUInteger) supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait; }
此处必有蹊跷!
我们火速进行修复尝试:
将图片选择器界面的视图控制器的
supportedInterfaceOrientations方法返回值改为
UIInterfaceOrientationMaskPortrait
编译联调验证,果然没有发生崩溃。
我们断定在iOS8.3系统出现的
UIAlertView发生崩溃的根本原因可能在于此,于是又将
QQMarkActionSheetController_FixPos中重写的
shouldAutorotate方法删除,测试验证发现没有发生崩溃,继续验证其他曾发生崩溃的场景,崩溃问题没有发生。
终于,我们得出此崩溃问题的根因。
崩溃原因总结
如果在视图控制器中重写supportedInterfaceOrientations方法,并将返回值设为
UIInterfaceOrientationPortrait的话,那么在此视图控制器或子视图中弹出
UIAlertView时,就会发生崩溃。
查阅了开发文档了解
supportedInterfaceOrientations方法的使用,发现其返回值实际是
UIInterfaceOrientationMask类型,而项目中却返回了
UIInterfaceOrientation类型,二者虽然长得很相似,但用处完全不一样:
·
UIInterfaceOrientationMask类型用来表示
UIViewController能支持的方向
·
UIInterfaceOrientation类型用来表示
application当前的方向
如果在iOS8.3系统上两者混用,系统新增的检查判断会发现此问题,并抛出异常,崩溃就这样产生了。
小编有话说
· 在开发过程中对于系统常量的引用及其含义要加强关注,尤其是遇到此类“兄弟”模样的常量时,避免因理解不清或笔误而造成问题。· 在系统版本更新时,要及时关注系统API和常量定义的变化,对功能代码进行兼容性调整。
不总结哪来经验,不分享经验何用?
在此小编号召大家多总结,互分享,踊跃给我们投稿,把自己踩过并爬出来的坑树个指示牌警醒后人,让猿们的开发生活更加美好!
投稿方式:将文章和个人介绍邮件到 bugly@tencent.com,字数不限
本文系腾讯Bugly特邀文章,转载请注明作者和出处“腾讯Bugly(http://bugly.qq.com)”
相关文章推荐
- iOS崩溃堆栈符号化,定位问题分分钟搞定!
- 直接拿来用!最火的iOS开源项目(一)、(二)、(三)
- 腾讯Bugly与极客学院再次联手,首推「iOS Crash 跟踪方法」视频教程!
- iOS——armv7,armv7s,arm64详解
- iOS开发笔记2-使用Alcatraz管理Xcode的插件
- iOS 与 JS 交互
- iOS:新特性三(iOS5.0/xcode4.2)--ARC
- iOS duplicate symbol 错误
- iOS 判断字符串是否含有某种字符
- ios 拆分字符串为数组
- ios 深刻理解MVC模式—代理方法
- iOS开发-音乐播放(AVAudioPlayer)
- iOS7开发者应该的知识体系
- 一步一步实现iOS应用PUSH功能
- 常用的排序算法
- iOS多线程编程
- iOS多线程编程NSOperation的使用
- iOS编码
- iOS音频
- iOS开发人员单元测试要求