会记录一些奇葩的闪退问题。
1.今日遇到一个闪退情况,在iOS8中UIScrollView在放大缩小的时候闪退。
前提:进入界面就会调用接口等接口回来后视图放大功能,在放大动画还没有做的时候,返回到上一界面,然后再次进入当前的ViewController 闪退。
设备:6Plus
设备系统:iOS8 (其他系统调用没有这个问题,可能iOS7 也存在当前这个问题。)
闪退的日志如下:
0 libobjc.A.dylib 0x000000019640bbd0 objc_msgSend + 16
1 UIKit 0x000000018a49b86c -[UIScrollView _getDelegateZoomView] + 76
2 UIKit 0x000000018a49b7ac -[UIScrollView _zoomScaleFromPresentationLayer:] + 32
3 UIKit 0x000000018a6af5c4 -[UIScrollView _zoomAnimationDidStop] + 96
4 UIKit 0x000000018a483c08 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 184
5 UIKit 0x000000018a483b10 -[UIViewAnimationState animationDidStop:finished:] + 100
6 QuartzCore 0x0000000189da8f60 CA::Layer::run_animation_callbacks(void*) + 292
7 libdispatch.dylib 0x0000000196a3d368 _dispatch_client_callout + 12
8 libdispatch.dylib 0x0000000196a4197c
根据闪退日志显示,是UIScrollView 在做放大缩小的时候调用了 getDelegateZoomView (delegate 中的 viewForZoomingInScrollView )这个方法,然后开始调用objc_msgSend (消息传递 不懂的可以看下Runtime方面的知识)方法执行后出现闪退。
分析情况:如果调用方法的时候发现闪退,就是被调用的类没有当前这个方法而闪退。 那么出现的情况是:1.当前的这个类已经被释放,2.当前的这个类并没有实现当前这个方法。
排除第2种猜测,原因是当前在使用正常的情况下是没有问题的,当前的ViewController 也实现了 viewForZoomingInScrollView 这个方法。
所以是当前这个ViewController已经被释放了,但是还是调用了delegate viewForZoomingInScrollView方法。
目前的情况是只出现在iOS8设备上,猜测iOS8 上ViewController释放了但是UIScrollView delegate 没有释放。
修改方法:
1.在ViewController 释放的时候 dealloc这个方法中,对 UIScrollView.delegate = nil;
- (void)dealloc{
_scrollView.delegate = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
为什么使用 _scrollView 呢?
当前的scrollView是懒加载的方式,如果在dealloc中调用 self.scrollView 会重新去调用ScrollView的生成 从而引发内存不释放的问题。
思考: 拿到Crash日志,一看系统调用的时候挂了,就归类到系统问题了,无法处理。有时候坚持一下,多看一会儿,多想一下,尝试去Google上搜一下Crash信息中的一些字段,或许别人也有遇到过相同或者相似的问题,说不定得到启发从而解决了一个看似没法解决的问题。