IOS —— Crash分析

1. Crash

应用崩溃是影响 APP 体验的重要一环, 而崩溃定位也常常让开发者头疼。Crash的出现就是做了一些违背代码规则的操作,常见crash类型有:

  • 容器越界
  • 使用未初始化的变量
  • 用户授权问题
  • 选择器方法未定义
  • 子线程刷新ui
  • KVO
  • 数据类型不匹配
  • 内存溢出
  • 野指针
  • 死循环
    那么该如何高效处理Crash呢?

2. 奔溃处理

2.1 选择器方法未定义

下面这个代码明显的会崩溃,因为没有logicEdu方法。

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}
- (IBAction)btnAction:(UIButton *)sender {
    [sender performSelector:@selector(logicEdu:)];
}
@end

那么添加下面这个方法之后还是崩溃。

- (void) logicEdu:(UIButton *)sender {
    
}

首先看一下堆栈。这里exception_throw是异常抛出的意思,而抛出异常的地方是+[NSObject(NSObject) instanceMethodSignatureForSelector:] 也就是慢速消息转发里面。消息发送中会通过对象的isa找到类去类的方法列表里面寻找selector,如果没有找到则去类的父类里面查找,直到找到NSObject还没有找到的话就会进入消息转发流程,
在这里插入图片描述
消息转发流程里面有三个补救的机会:

  • 动态方法决议(添加方法)
  • 快速消息转发(转发给另一个对象来处理)
  • 慢速消息转发(动态签名签名一个sel)
    如果这三个都没有处理,那么就会崩溃。
    这里来创建一个NSObject分类来进行快速消息转发 -forwardingTargetForSelector;
@implementation NSObject (method)
- (id)forwardingTargetForSelector:(SEL)aSelector {
    id result = [self forwardingTargetForSelector:aSelector];
    return result;
}
@end

这里会报警告,因为分类方法名字和主类的方法名字一样,这时候就需要用到method-Swizzing进行imp交换。这里运行后发现还是崩溃的。method-Swizzing一般是在load里面实现,load在main函数之前就会被调用,并且是主动调用,但是在load写函数会影响启动速度,应该尽量不要在load中写耗时的操作。并且类和分类是懒加载的,但是如果实现了load,那么类的加载就会提前到main函数之前。影响启动速度的原因是会在底层调用更多的方法比如attchCategory等。 有的把方法交换写到initialize里面,这也是可以的,因为initialize是第一次调用方法的时候被调用的。但是不建议在initialize里面进行方法交换,因为可能不会调用方法。

+ (void)load {
 
    Method originalMethod = class_getInstanceMethod(self, @selector(forwardingTargetForSelector:));
    Method swizzleMethod = class_g
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值