由NSAarry Method Swizzle引发的血案

由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引发的血案_第1张图片
由NSAarry Method Swizzle引发的血案_第2张图片
3、找一个可以显示keyboard的界面,打开keyboard,按Home键退出,再点击图标打开,就可以看到crash了。
这里写图片描述
  其实解决方法也很简单,就是去除NSMutableArray 的方法替换,但是这么做不是很优雅,因为我们的项目几乎不用objectAtIndex:方法,而是用拓展了另一个方法,所以直接干掉了,也可以参考这篇文章的做法:
http://www.cnblogs.com/DamonTang/p/4342366.html
不过个人认为,对NSArray的通用方法进行替换可能会引起一些意想不到的问题,所以还是最好不要用,我们的项目最近正考虑干掉NSAarry Method Swizzle。

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