盒子
盒子
文章目录
  1. iOS常见的几种Crash类型
  2. unrecognized selector crash
    1. 首先需要了解方法调用的大概流程
      1. 注:
  3. 几个关键的方法

iOS Crash 小计

iOS应用Crash是令我们开发者比较头疼的一件事情。比如线上应用的闪退,老板会很慌,你比老板更慌。所以说,有没有一劳永逸的办法来解决呢,看了网易的大白崩溃,感觉又发现了新大陆。附:Demo 不定期更新中….

iOS常见的几种Crash类型

  • unrecognized selector crash
  • KVO crash
  • NSNotification crash
  • NSTimer crash
  • Container crash(数组越界,插nil等)
  • NSString crash (字符串操作的crash)
  • UI not on Main Thread Crash (非主线程刷UI(机制待改善))
  • Thread 1:EXC_BAD_ACCESS(code=EXC_I386_GPFLT)(野指针)

unrecognized selector crash

首先需要了解方法调用的大概流程

  • 首先,在相应操作的对象中的缓存方法列表中找调用的方法,如果找到,转向相应实现并执行。

  • 如果没找到,在相应操作的对象中的方法列表中找调用的方法,如果找到,转向相应实现执行

  • 如果没找到,去父类指针所指向的对象中执行1,2.

  • 以此类推,如果一直到根类还没找到,转向拦截调用,走消息转发机制。

  • 如果没有重写拦截调用的方法,程序报错。

注:
  • 普通方法的优先级: 分类> 子类 > 父类, 优先级高的同名方法覆盖优先级低的
  • +load方法的优先级: 父类> 子类> 分类
  • +load方法是在main() 函数之前调用,所有的类文件都会加载,包括分类
    +load方法不会被覆盖
  • 同一主类的不同分类中的普通同名方法调用, 取决于编译的顺序, 后编译的文件中的同名方法会覆盖前面所有的,包括主类. +load方法的顺序也取决于编译顺序, 但是不会覆盖
    分类中的方法名和主类方法名一样会报警告, 不会报错
    声明和实现可以写在不同的分类中, 依然能找到实现
    当第一次用到类的时候, 如果重写了+ initialize方法,会去调用
    当调用子类的+ initialize方法时候, 先调用父类的,如果父类有分类, 那么分类的+ initialize会覆盖掉父类的, 和普通方法差不多
    父类的+ initialize不一定会调用, 因为有可能父类的分类重写了它

几个关键的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
+ (BOOL)resolveClassMethod:(SEL)sel;

+ (BOOL)resolveInstanceMethod:(SEL)sel;

//后两个方法需要转发到其他的类处理

- (id)forwardingTargetForSelector:(SEL)aSelector;

- (void)forwardInvocation:(NSInvocation *)anInvocation;


这里我们选择了第二步forwardingTargetForSelector来做文章。原因如下:

resolveInstanceMethod 需要在类的本身上动态添加它本身不存在的方法,这些方法对于该类本身来说冗余的
forwardInvocation可以通过NSInvocation的形式将消息转发给多个对象,但是其开销较大,需要创建新的NSInvocation对象,并且forwardInvocation的函数经常被使用者调用,来做多层消息转发选择机制,不适合多次重写
forwardingTargetForSelector可以将消息转发给一个对象,开销较小,并且被重写的概率较低,适合重写

先写到这。。。来活了。。。

dd

支持一下
扫一扫,支持ddSoul