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 ...
随机推荐
- SDP(11):MongoDB-Engine功能实现
根据上篇关于MongoDB-Engine的功能设计方案,我们将在这篇讨论里进行功能实现和测试.下面是具体的功能实现代码:基本上是直接调用Mongo-scala的对应函数,需要注意的是java类型和sc ...
- 【BZOJ3223】文艺平衡树(Splay)
题面 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 ...
- 百度统计&友盟统计
一.百度统计 登录百度站长统计账号-->管理 --->代码获取-->复制代码,如 <script> var _hmt = _hmt || []; (function() ...
- angularjs中的下拉框默认选中
1. ng-init 属性: <!DOCTYPE html> <html> <head> <meta charset="utf-8"& ...
- c#多线程同步之lock
一提起lock,想必大家都很熟悉,因为它易用,顾名思义,就是一把锁,常用于多线程的同步,一次只允许一个线程进入.最近遇到一个很诡异的bug. private static readonly objec ...
- UML 中extend和include的区别
在UML用例图中有两种关系——包含和扩展,容易混淆,下面通过一张表来区别一下这两种关系.
- Java并发编程实战(chapter_1)(原子性、可见性)
混混噩噩看了很多多线程的书籍,一直认为自己还不够资格去阅读这本书.有种要高登大堂的感觉,被各种网络上.朋友.同事一顿外加一顿的宣传与传颂,多多少少再自我内心中产生了一种敬畏感.2月28好开始看了之后, ...
- MySQL多数据源笔记3-分库分表理论和各种中间件
一.使用中间件的好处 使用中间件对于主读写分离新增一个从数据库节点来说,可以不用修改代码,达到新增节点数据库而不影响到代码的修改.因为如果不用中间件,那么在代码中自己是先读写分离,如果新增节点, 你进 ...
- Ubuntu14.04安装pycharm用于Python开发环境部署,并且支持pycharm使用中文输入
一.目标 实现在Linux下用pycharm调试工具/Python开发 Linux使用vi/vim工具写Python,缺点:调试不方便,无代码提示.跳转等诸多功能. Windows使用idle/pyc ...
- @Controller 类中初始化问题解决办法
在Controller类中常常遇到有些参数需要初始化,甚至有些只允许初始化一次,而Controller类不像servelet类可以调用init()函数进行初始化,这里想到的办法是设置标记值,让初始化部 ...