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