欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

由NSAarry Method Swizzle引发的血案

程序员文章站 2022-06-08 08:22:04
...

由NSAarry Method Swizzle引发的血案

  近期项目上线后,发现一个频率较高的crash,crash信息如下:

libobjc.A.dylib 0x00000001899857f4 objc_object::release() + 8
1   libsystem_blocks.dylib  0x0000000189e13a68 __Block_release + 160
2   UIKit   0x0000000191ac586c -[UIKeyboardTaskEntry dealloc] + 68
3   libobjc.A.dylib 0x0000000189986134 (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 836
4   CoreFoundation  0x000000018ade2b28 __CFAutoreleasePoolPop + 28
5   UIKit   0x00000001912b67a4 __prepareForCAFlush + 596
6   UIKit   0x000000019102a6b0 __afterCACommitHandler + 236
7   CoreFoundation  0x000000018aeb49a8 ___CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 32
8   CoreFoundation  0x000000018aeb2630 ___CFRunLoopDoObservers + 372
9   CoreFoundation  0x000000018aeb2a7c ___CFRunLoopRun + 956
10  CoreFoundation  0x000000018ade2da4 _CFRunLoopRunSpecific + 424
11  GraphicsServices    0x000000018c84c074 _GSEventRunModal + 100
12  UIKit   0x000000019109d058 _UIApplicationMain + 208
13  Knight  0x00000001000c7c54 main (main.m:14)
14  libdyld.dylib   0x0000000189df159c _start + 4

  乍一看似乎是系统的crash,但是每一个crash都是有原因的,所以就查了一下这个crash,然后发现遇到的人还挺多。其实产生这个crash的原因是我们的项目对NSArray和NSMutableArray的objectAtIndex:方法进行了运行时替换,以防止空插、越界等情况。注意上面说的是同时对NSArray和NSMutableArray的objectAtIndex:方法进行替换,如果只替换了NSArray的方法,则不会产生上述crash。
crash复现的步骤如下:
1、连接手机
2、打开xcode的Zombie Objects.打开方法为Edit Scheme -> Run -> Diagonstics
由NSAarry Method Swizzle引发的血案
由NSAarry Method Swizzle引发的血案
3、找一个可以显示keyboard的界面,打开keyboard,按Home键退出,再点击图标打开,就可以看到crash了。
由NSAarry Method Swizzle引发的血案
  其实解决方法也很简单,就是去除NSMutableArray 的方法替换,但是这么做不是很优雅,因为我们的项目几乎不用objectAtIndex:方法,而是用拓展了另一个方法,所以直接干掉了,也可以参考这篇文章的做法:
http://www.cnblogs.com/DamonTang/p/4342366.html
不过个人认为,对NSArray的通用方法进行替换可能会引起一些意想不到的问题,所以还是最好不要用,我们的项目最近正考虑干掉NSAarry Method Swizzle。