iOS中的 uncaught exception 主要有哪些

iOS 中的错误分为 NSError 和 NSException,其中NSError用于可恢复的错误,而NSException则是不可恢复的错误,对于NSException我们可以通过NSSetUncaughtExceptionHandler来进行崩溃的捕获获取,那么常见的 NSException 有哪些呢?

  • 数组越界访问
NSArray *array = @[@"2"];
NSString *aa = array[2];
//	对应崩溃错误信息
//	Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 2 beyond bounds [0 .. 0]'
  • KVC赋值给一个没有定义的key
[[UIViewController new] setValue:@"Jack" forKey:@"name"];
//	对应的崩溃错误信息
//	Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key name.'
  • 字典中键或值插入空值 nil
NSString *key1 = nil;
NSString *value1 = nil;
NSDictionary *dic1 = @{key1:@"USA"};
//	对应的崩溃信息
//	Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[0]'
或者
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
[dic setObject:value1 forKey:@"USA"];
也会发生崩溃,但是通过KVC的方式如
[dic setValue:value1 forKey:@"USA"];
却不会发生崩溃,对于字典的KVC方法可以查看
/* Send -setObject:forKey: to the receiver, unless the value is nil, in which case send -removeObjectForKey:.
*/
- (void)setValue:(nullable ObjectType)value forKey:(NSString *)key;
所以相对健壮
  • NSAttributedString初始化时传入空值nil
NSString *string = nil;
NSAttributedString *AttributedString = [[NSAttributedString alloc] initWithString:string];
//	对应的崩溃信息
//	Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'NSConcreteAttributedString initWithString:: nil value'
  • unrecognized selector
[[UIViewController new] performSelector:@selector(test)];
//	对应的崩溃信息
//	Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIViewController test]: unrecognized selector sent to instance 0x7fe479706a10'
  • UITableView 中没有注册cell重用标识,取空的cell为空
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
   //	之前并没有在tableView中注册该重用标识
   UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell1" forIndexPath:indexPath];
   cell.textLabel.text = [NSString stringWithFormat:@"第%zd行",indexPath.row];
   return cell;
}
//	对应的崩溃信息
//	*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier cell1 - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'

另外更新UITableView数据时,前后的数据不同步也会导致该类型的错误

  • Push到同一个控制器多次
 TableViewController *TC = [TableViewController new];
  [self.navigationController pushViewController:TC animated:YES];
  [self.navigationController pushViewController:TC animated:YES];
  [self.navigationController pushViewController:TC animated:YES];
//	对应的崩溃信息
//	Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Pushing the same view controller instance more than once is not supported ()'

那么对于iOS 提供的 try-catch 可以捕获上述哪几种错误呢?

  • unrecognized selector
  • NSAttributedString初始化时传入空值nil
  • 数组越界访问
  • KVC赋值给一个没有定义的key
  • 字典中键或值插入空值 nil
  • NSAttributedString初始化时传入空值nil

可见try-catch来说,其能抓取的错误是有限的,对于内存溢出和野指针问题无能为力;除此之外,try-catch还可能产生以下问题

  • 即使在ARC下,内存释放的代码会因为try-catch的中断不能执行,会造成内存泄漏;对于采用GC来释放内存的java等语言,不会存在此问题
  • exception使用block造成额外的开销,效率较低

基于上述原因,iOS中的try-catch使用并不如Android开发中使用的那么频繁

你可能感兴趣的:(iOS移动开发)