【团队分享】iOS8.3给发图带来的坑,怎样迅速填平?

来源:互联网 发布:凤凰金融 网络凤凰网 编辑:程序博客网 时间:2024/04/30 10:51


向华,手机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)”

0 0
原创粉丝点击