问题:启动秒退
在新 iOS 上正常的应用,到了老版本 iOS 上秒退最常见原因是系统动态链接库或Framework无法找到。这种情况通常是由于 App 引用了一个新版操作系统里的动态库(或者某动态库的新版本)或只有新 iOS 支持的 Framework,而又没有对老系统进行测试,于是当 App 运行在老系统上时便由于找不到而秒退。解决办法是等开发人员发现这个问题后升级程序,或由用户自行升级其操作系统。
还有一种常见的秒退是程序在升级时,修改了本地存储的数据结构,但是对用户既存的旧数据没有做好升级,结果导致初始化时因为无法正确读取用户数据而秒退。这类问题通常只需删除程序后重新安装一遍就能解决。但缺点是用户的既存数据会丢失——就算有备份可能也无济于事,因为备份下来的旧数据还是无法被正确升级。
还有一类秒退或是用到 App 里某个功能后必退的原因,是开发时用到了只有新版操作系统才支持的某个方法,而又没有对该方法是否存在于老系统中做出判断。例如程序启动时用到了 Game Center,而没有判断用户的机器是否支持 Game Center,于是就秒退了。
问题:访问的数据为空或者类型不对
这类情况是比较常见的,后端传回了空数据,客户端没有做对应的判断继续执行下去了,这样就产生了crash。或者自己本地的某个数据为空数据而去使用了。还有就是访问的数据类型不是期望的数据类型而产生崩溃。比如,我期望服务端返回string类型,但是后台给我返回的是NSNumber类型,那么我操作时候用到的是string的方法。结果因为找不到对应的方法而崩溃。解决办法:1、服务端都加入默认值,不返回空内容或无key。或者是在客户端进行非空判断。2、对容易出错的地方提前进行类型判断。
问题:点击事件方法处理不当
这类情况比较常见,比如我的点击事件需要对传入的参数做处理,但是点击时,我传入的对象类型或者传入为空,等到参数进行处理的时候,由于方法不当,产生crash。
问题:数组越界
当客户端尝试对数组中的数据进行操作的时候,数组为空或者所做的操作index 超过数组本身范围,就会引起崩溃。
问题:下拉刷新时崩溃
使用下拉刷新时,如果下拉的距离长了就会崩溃。原因是,在下拉刷新请求数据之前就将本地数组清空了。分析,下拉刷新的逻辑:1、下拉 2、下拉达到临界值时触发网络请求 3、等待数据加载到本地以后才更新datasource 4、tableview reloadData。 如果先清空数组再下拉请求,后果就是往下拉的距离超过一个 cell 的高度时,table view 的几个委托方法就会被调用,由于 data source 已经被清空,造成错误的内存访问(包括数组越界,访问已销毁的对象)导致 crash。
问题:操作了不该操作的对象、野指针
iOS中有空指针和野指针两种概念。
空指针是没有存储任何内存地址的指针。如Student s1 = NULL;和Student s2 = nil;
而野指针是指指向一个已删除的对象("垃圾"内存既不可用内存)或未申请访问受限内存区域的指针。野指针是比较危险的。因为野指针指向的对象已经被释放了,不能用了,你再给被释放的对象发送消息就是违法的,所以会崩溃。
野指针访问已经释放的对象crash其实不是必现的,因为dealloc执行后只是告诉系统,这片内存我不用了,而系统并没有就让这片内存不能访问。
所以野指针的奔溃是比较随机的,你在测试的时候可能没发生crash,但是用户在使用的时候就可能发生crash了。
注意:arc环境比非arc环境更少出现野指针。
1、对象释放后内存没被改动过,原来的内存保存完好,可能不Crash或者出现逻辑错误(随机Crash)。
2、对象释放后内存没被改动过,但是它自己析构的时候已经删掉某些必要的东西,可能不Crash、Crash在访问依赖的对象比如类成员上、出现逻辑错误(随机Crash)。
3、对象释放后内存被改动过,写上了不可访问的数据,直接就出错了很可能Crash在objc_msgSend上面(必现Crash,常见)。
4、对象释放后内存被改动过,写上了可以访问的数据,可能不Crash、出现逻辑错误、间接访问到不可访问的数据(随机Crash)。
对象释放后内存被改动过,写上了可以访问的数据,但是再次访问的时候执行的代码把别的数据写坏了,遇到这种Crash只能哭了(随机Crash,难度大,概率低)!!
5、对象释放后再次release(几乎是必现Crash,但也有例外,很常见)
问题:内存处理不当
用instruments排查内存泄露问题
问题:主线程UI长时间卡死,被系统杀掉
主线程被卡住是非常常见的场景,具体表现就是程序不响应任何的UI交互。这时按下调试的暂停按钮,查看堆栈,就可以看到是到底是死锁、死循环等,导致UI线程被卡住。
问题:多线程之间切换访问引起的crash
多线程引起的崩溃大部分是因为使用数据库的时候多线程同时读写数据库而造成了crash。
问题:内存紧张
这个现在很少遇到了。