内容简介:作为一个刚毕业从事iOS开发不久的人,最初同事以及导师都叮嘱我写代码的时候一定要注意异常情况,底线就是不能写出任何有可能造成崩溃的代码。实际上,项目中有监测崩溃的工具,而且review的时候也会很严格检查,所以基本上那种有可能造成崩溃的代码基本都会在上线前修正。但就在前些天,客户端发生了大面积一打开就闪退的问题,影响非常严重,后来查出是引入的其他部门的SDK没有进行类型判断而导致的崩溃。或许是开发人员的不小心,但我觉得更多的是平时没有养成习惯,没有考虑到对于一个拥有千万级别用户的应用来说,即使是万分之一的崩
作为一个刚毕业从事iOS开发不久的人,最初同事以及导师都叮嘱我写代码的时候一定要注意异常情况,底线就是不能写出任何有可能造成崩溃的代码。实际上,项目中有监测崩溃的工具,而且review的时候也会很严格检查,所以基本上那种有可能造成崩溃的代码基本都会在上线前修正。
但就在前些天,客户端发生了大面积一打开就闪退的问题,影响非常严重,后来查出是引入的其他部门的SDK没有进行类型判断而导致的崩溃。或许是开发人员的不小心,但我觉得更多的是平时没有养成习惯,没有考虑到对于一个拥有千万级别用户的应用来说,即使是万分之一的崩溃概率,也会有数千个用户崩溃,这在竞争激烈的互联网市场,是不能被容忍的。
我平时也没有过度重视,因为我总觉得理论上应该不可能崩溃,但是实际的场景太多,理论上不可能并不是百分百不可能,作为足够严谨的开发人员,必须守住自己的底线,不只是知道什么情况会造成崩溃,而是要养成一种编程习惯,所以特意分析了各种崩溃的情况。
数组越界
NSArray *firstNames = @[@"Roy", @"Mike", @"Jordan"]; NSString *name = firstNames[3]; // 崩溃 崩溃信息: **** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndexedSubscript:]: index 3 beyond bounds [0 .. 2]' ***** 分析: 可以看出当前数组的范围是0..2,当前下标超出了范围,即访问了未知的内存空间 注: 除了数组可能越界之外,字符串也有可能越界,例如执行substringWithRange:消息时如果传递了过大的范围也会崩溃 复制代码
字面量数组和字典插入nil值
数组
NSString *name; NSArray *firstNames = @[@"Roy", @"Mike", @"Jordan", name]; //崩溃 崩溃信息: **** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[3]'* ***** 分析: 通过崩溃信息可以很清楚看到是因为在字典初始化的时候插入了nil,实际上字面量语法是一种语法糖,本质是先创建了一个数组,然后把方括号内的所有对象添加到这个数组中 注: 字面量语法让代码更加简洁,也能及时发现错误,但是最后创建的数组是不可变的 复制代码
字典
NSNumber *jordanAge; NSDictionary *ages = @{@"Roy":@22, @"Mike":@24, @"Jordan":jordanAge}; //崩溃 崩溃信息: **** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[2]'* ***** 分析: 同上面原因一样,都是插入了nil而导致的崩溃 注: 当key为nil的时候插入也会崩溃 复制代码
Unrecognized Selector
id person = @"person"; [person objectForKey:@"name"]; //崩溃 崩溃信息: **** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFConstantString objectForKey:]: unrecognized selector sent to instance 0x1000010e8'* ***** 分析: person对象无法执行objectForKey:消息,所以最后崩溃了 注: 在用Objective-C语言编码时,我们会常常使用id类型更加便利地声明变量,但在执行消息前一定要确定它是否能响应,可使用respondsToSelector:检查。最常见的场景是调用代理方法,即使指定了代理对象,也不一定保证代理实现了相应方法(协议里还有可选实现的方法) 复制代码
NaN崩溃
float number = NAN; NSDictionary *dict = @{@"value" : @(number)}; NSData *data = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingSortedKeys error:nil]; 崩溃信息: **** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid number value (NaN) in JSON write'* ***** 分析: 可以先来判断dict对象是否能被转换成JSON数据: BOOL isValidJSONObject = [NSJSONSerialization isValidJSONObject:dict]; isValidJSONObject的结果是NO,也就是dict对象无法被转换为JSON数据,即NaN类型不能被用于JSON对象中 注: 当进行不正常的数学运算时不只是会产生NaN类型,也有可能产生+inf类型,虽然并不会直接造成崩溃,但有可能在用它们进行其他操作的时候会有可能造成崩溃。通过isnan(x)和isinf(x)方法可以判断nan和inf类型 复制代码
富文本初始化时字符串为空
NSString *text; NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:text]; // 崩溃 崩溃信息: **** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'NSConcreteAttributedString initWithString:: nil value'* ***** 分析: 从崩溃信息中可以很明显看到是因为传入的变量值为nil而崩溃 注: 构造NSMutableString时,如果传入的字符串为nil也会崩溃 复制代码
创建未注册过的UITableViewCell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"reuseIdentifier" forIndexPath:indexPath] // 崩溃 复制代码
服务器端出现问题而造成的崩溃
有一种情况,就是服务器端传递数据给客户端,客户端将其解析成模型对象,然后取模型里的值插入字面量语法构造的数组或者字典中。如果服务器端发生了问题,而客户端没有保护措施就会受到连累,当然实际上服务器端百分之九十九的概率是不可能发生问题的,所以很多人(包括我)也理所当然不会去特意多写一些多余的防御性代码。 我上面只是举了一个例子,一般我们都会和服务器端约定好数据格式以及其他细节,而且大多数时候都会做一些保护,但我真正想强调的是 客户端不崩溃一定优于客户端依赖于服务器端而不崩溃 ,尽可能避免受到外界的影响
其他崩溃
- 在iOS 9.0之后NSNotificationCenter不会对一个dealloc的观察者发送消息,所以如果应用最低版本是9.0,其实也不必每次都去移除通知,但如果需要支持更低的版本,还是一定要移除通知,否则会崩溃
- KVO不移除监听会导致奔溃,所以KVO的添加和移除必须成双成对
- 内存泄露,最著名的是代理和被代理对象循环引用
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
翻转课堂的可汗学院
萨尔曼·可汗(Salman Khan) / 刘婧 / 浙江人民出版社 / 2014-4-1 / 49.00元
MIT和哈佛毕业的高材生缘何放弃金融分析师工作投身教育事业?YouTube上的“可汗学院频道”至今共吸引了163.3万订阅者,观看次数超过3.55亿次,它为什么如此大受欢迎?创始人萨尔曼·可汗阐述属于未来的教育理念——让地球上的任何人都能随时随地享受世界一流的免费教育! 现行教育模式已有200余年历史,可汗认为,在互联网蓬勃发展、社交网络盛况空前的时代,免费、灵活、适合个体、全球共享的教育才......一起来看看 《翻转课堂的可汗学院》 这本书的介绍吧!