UI事务重叠引发的crash
在ios开发的世界里,通过动画来切换界面使我们早就习以为常的事情,但动画将一个原本同步执行的事务,变成一个异步事务,并由此引发了一系列的陷阱。
最近对公司产品的crashlytics报告进行了一些分析,发现这类bug在各个产品里都占据较高比例,因此总结了一下常见的case。
present ViewController引发的混乱
present一个controller的时候,如果一个present的动画正在执行过程当中,程序会抛出异常,异常告诉你Attempting to begin a modal transition from * to * while a transition is already in progress. Wait for viewDidAppear/viewDidDisappear to know the current transition has completed;
解决的办法是引入一个present事务控制器,用来对present请求进行排队,这种方案是否足够可靠,还有待验证。NavigationController引发的混乱
与present类似,NavigationController的push&pop也会引发类似的错误,症状是,在多重push的时候不会立即crash,视图的内容部分会一团漆黑,但是在回退的时候会crash,异常是Fatal Exception: NSInvalidArgumentException Can't add self as subview,从crash的调用栈看,是navigationbar内部错误。
解决的方法是可以继承UINavigationController,通过UINavigationControllerDelegate来监测状态,如果当前正在处于上一个push的执行过程当中,可以忽略掉新的push请求。UIScrollView(UITableView)的delegate引发的崩溃
虽然ios5.0开始就已经支持weak引用,但很多的cocoa Touch类的delegate属性还是assign,这说明他们保存了一个不安全的引用。UIScrollView就是这样,如果controller里面有个UIScrollView,delegate属性是自身,那么有可能发生这样的情况:uiscrollview正在进行一个动画事务(出问题的case中,动画往往不是由于用户操作导致的),用户退出了当前的controller,动画完成的时候controller可能已经被dealloc,此时会发生EXEC_BAD_ACCESS崩溃。
如果crash的的栈显示与UIScrollView有关,又表明是在Animation结束的时候,那么就很有可能是这个原因;这样的bug往往很难复现,据经验,一般出现在那些通过定时器启动动画的场合。
因此,作为一种防御性的手段,建议在controller的dealloc里面,将相关的delegate置为nil多个UI事件同时发生引发的混乱
一个同事提供的线索,如果你同时点击UI页面的多个可点击控件,UI有可能发生混乱。
比如同时点击多个button,uicontrol,绑定gesture的uiview等,只要刻意试一下我们的产品都有这个问题。
现在的解决的方案是将相关可点击view的exclusiveTouch属性设置为true,如果工程里面UI控件都是用工厂方法创建的,那么改起来还是很方便的。
不过gesture是不受这个属性的影响的,目前还没有发现如何解决,因此只能规避,如果能够使用UIControl来解决的问题,就不要使用UIView+Gesture来解决。
这种问题如果不是刻意的去操作,一般还是很少会暴露的。
上面的几点是最近对线上一类疑难bug分析之后总结出来的根本原因;其本质上都是UI事务叠加导致的。上面1和2发生的根源一般都是,定时器或后台逻辑促发的界面切换,恰好和另一个界面切换撞在了一起,因此在测试的时候可能很难发现;在用户手上复现的概率也不是特别高,但总是会出现。所以在设计应用的时候,最好要避免这种从非用户操作导致的界面切换。
如果每个UI事务都不加动画、同步完成,那么就不会有这些情况,但这是不可能的。驱动App运行的所有事件源,包括定时任务、异步任务、用户操作、外部事件(比如推送消息)等,叠加在一起,使得完全避免上述的情况几乎不可能,关键是ios的UI框架对此基本不设防,只能靠我们自己积累经验,谨慎小心。
UI事务重叠引发的crash的更多相关文章
- [转]Spring事务嵌套引发的血案---Transaction rolled back because it has been marked as rollback-only
原文地址:https://blog.csdn.net/f641385712/article/details/80445912 1.概述 想必大家一想到事务,就想到ACID,或者也会想到CAP.但笔者今 ...
- Spring事务嵌套引发的问题--Transaction rolled back because it has been marked as rollback-only
转载https://blog.csdn.net/f641385712/article/details/80445912 读了两边才找到问题
- 用Fragment制作的Tab页面产生的UI重叠问题
本文出处:http://blog.csdn.net/twilight041132/article/details/43812745 在用Fragment做Tab页面,发现有时候进入应用会同时显示多个T ...
- iOS:项目中疑难Crash问题集锦
项目中疑难Crash问题集锦 iOS App运行中遇到Crash的情况相信大家都遇到过,开发和者测试中遇到了可能很方便的办法就是直接拿着设备连接一下,然后使用Xcode自带的工具就可以解析出Crash ...
- JNI NDK开发Crash错误定位 调试
总结: 搜索backtrace 然后: $ /d/android-ndk-r10c/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86 ...
- Android NDK开发Crash错误定位[转]
使用 ndk-stack 的时候需要你的 lib 编译为 debug版的,通常需要下面的修改: 1. 修改 android.mk,增加,为 LOCAL_CFLAGS 增加 -g 选项 2. 修改 ap ...
- 一些Windows API导致的Crash以及使用问题总结
RegQueryValueEx gethostbyname/getaddrinfo _localtime64 FindFirstFile/FindNextFile VerQueryValue Crea ...
- Sqlserver事务隔离级别详解
sqlserver存储方式 页 sqlserver是以页的形式存储数据,每个数据页的大小为8KB,sqlserver会把空间分为多个页,sqlserver与数据交互单位最小的io操作就是页级 ...
- sqlserver Distributed Transaction 分布式事务
在webapi+ef+sqlserver开发项目时,利用transcope实现应用层级的事务时,偶尔会报分布式事务错误,而且很而复现,特别蛋疼.现将自己的解决方法初步整理下. 分析原因:搭建repos ...
随机推荐
- Excel VBA TextBox控件的滚动条不能刷新
问题:Excel中Textbox控件以及Form里的Textbox控件,当直接填充的内容很长时,滚动条不能实时刷新. 现象: 修改后: 原因: 虽然已经向Textbox的Text里设置了内容,但此时T ...
- 【BZOJ4736】温暖会指引我们前行(Link-Cut Tree)
[BZOJ4736]温暖会指引我们前行(Link-Cut Tree) ##题面 神TM题面是UOJ的 题解 LCT傻逼维护最大生成树 不会的可以去做一做魔法森林 #include<iostrea ...
- 【HDU1695】GCD(莫比乌斯反演)
[HDU1695]GCD(莫比乌斯反演) 题面 题目大意 求\(a<=x<=b,c<=y<=d\) 且\(gcd(x,y)=k\)的无序数对的个数 其中,你可以假定\(a=c= ...
- [POI2000]病毒
题面 传送门 Sol 建出AC自动机后DFS能走的点,如果能走回来就可行 # include <bits/stdc++.h> # define IL inline # define RG ...
- luoguP2711 小行星
题目描述 星云中有n颗行星,每颗行星的位置是(x,y,z).每次可以消除一个面(即x,y或z坐标相等)的行星,但是由于时间有限,求消除这些行星的最少次数. 输入输出格式 输入格式: 第1行为小行星个数 ...
- 打印Java异常堆栈信息
背景 在开发Java应用程序的时候,遇到程序抛异常,我们通常会把抛异常时的运行时环境保存下来(写到日志文件或者在控制台中打印出来).这样方便后续定位问题. 需要记录的运行时环境包含两部分内容:抛异常时 ...
- Web前端有价值的博客文章汇总
一.HTML 二.CSS 1.深入理解position和z-index属性 :https://www.cnblogs.com/zhuzhenwei918/p/6112034.html 2.BFC(清除 ...
- handsontable 渲染实例
单元格选择完成后将触发事件afterSelectionEnd, 然后在js中: hot.addHook('afterSelectionEnd', function(r, c, r2, c2){ // ...
- CSS之盒子模型(深入理解)
CSS--盒子模型(Box Model) 简介: CSS盒子模型本质上是一个盒子,对网页中绝大部分的HTML元素进行包装定位(外边距,边框,内边距以及实际内容). 但是并不是所有的HTML元素都可以看 ...
- .Net调用钉钉接口,实现发送企业消息功能
我在钉钉官网上看了下,关于调用钉钉接口,发送企业消息通知,他给的核心代码总共几行. 用到的一个接口引用 TopSDK.dll 下载网址https://open-doc.dingtalk.com/doc ...