几个系统级崩溃问题和h5加载页面崩溃问题及解决方案

来源:互联网 发布:k线图软件下载 编辑:程序博客网 时间:2024/05/29 19:15

众所周知系统级崩溃定位不到代码的具体函数,一般都是内存释放时异常,空指针,越界访问问题。再加上苹果应用在切换到后台,杀线程问题,io资源在后台不可以申请问题(当在后台连续断网10分钟,就是定位应用的线程也会被杀掉)。这都是苹果应用一般比安卓应用运行流畅,而开发者对问题定位和线程守护感到头疼的问题。
第一个问题:
h5页面在加载出来前来回多次进入又退出h5页面,导致崩溃。
原因:
第三方库WebViewJavascriptBridgeBase没有进行对是否在主线程进行判断。
修改方案:
if ([NSThread isMainThread])
{
[self _evaluateJavascript:javascriptCommand];
}
else
{
dispatch_sync(dispatch_get_main_queue(), ^{
if(javascriptCommand.length == 0)
{
return;
}
[self _evaluateJavascript:javascriptCommand];
});
}
第二个问题:
应用启动时,收到网络检查结果通知早于第一个页面加载出来的部分手机,导致启动高频率崩溃。
原因分析:
这个问题很多应用都存在应用应用崩溃问题。这种崩溃首先和手机有关,有的手机会高频率发生,有的手机不会发生。这个和受限网络也相关,在手机连接受限网络的情况下,大部分手机的应用都出现启动应用崩溃(网络请求快于首页面的加载)。本质原因是苹果网络检查库(Reachability),没有对是否在主线程进行判断,直接发送网络通知。导致应用还在系统子线程里,没有加载出第一个页面并且获取到主线程的运行权限。导致直接在子线程里发送通知而崩溃。这个你可以通过在didFinishLaunchingWithOptions发送系统通知而百分之百的再现。
修改的非彻底方案:
// this makes sure the change notification happens on the MAIN THREAD
if ([NSThread isMainThread])
{
[[NSNotificationCenter defaultCenter] postNotificationName:kReachabilityChangedNotification
object:self];
}
else
{
dispatch_sync(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:kReachabilityChangedNotification
object:self];
});
}
第三个问题:
当通知正在通知中心中注册过程中,还没注册成功时,一个子线程发送了对应的通知,就会产生崩溃。
问题解决方案分析:
所以在发送通知时一定要保证,对应的通知不时在正注册过程中。这种几率虽然不高,但是也是存在的,并且已经再现出来。
经典的案例:
在应用的首个页面(每次启动应用必然看到第一个页面)viewDidLoad函数注册网络通知监听,在didFinishLaunchingWithOptions初始化网络检查(开始网络检查,注意当初始化两次及以上网络检查时,系统发现网络变更时会发送两次网络变更通知,所以一定要保证只初始化一次网络检查)。有低概率出现启动应用时崩溃,崩溃栈含有UIApplicationMain。
针对启动应用时由于网络检查的崩溃解决方案解决方案如下,类似的问题可以参照处理。
在应用启动的第一个页面的第一次调用viewDidLoad函数中初始化网络检查。这个方案可以和第二个问题的解决方案结合彻底解决应用启动时由于网络检查引起的崩溃问题。
注意:应用启动的页面并非一定根页面,第一个页面可能被销毁,如有侧边栏的应用,侧边栏的登录页面才时根页面,第一个页面可能是主控制器的页面,非侧边栏控制器页面都可能被pop出来。
第四个问题:
在子线程里发送通知,在通知处理函数中不会主线程直接刷新ui引起系统崩溃。
解决方案:
在子线程里发送通知前,判断是否在主线程,若不在主线线程就回主线程,然后再发送通知。这样即好统一管理,实现又简单。
if ([NSThread isMainThread])
{
if(self.offLineSuccessBlock != nil)
{
self.offLineSuccessBlock(YES);
}
self.hitOnOffLineTime = 0;
}
else
{
dispatch_sync(dispatch_get_main_queue(), ^{
if (self.hitOnOffLineTime > 0)
{
if(self.offLineSuccessBlock != nil)
{
self.offLineSuccessBlock(YES);
}
self.hitOnOffLineTime = 0;
}
});
}
第五个问题:
block为空时返回崩溃问题。
解决方案:
在block处理产生时记录一个时间和block指针。当block返回受限保证这个记录时间有效并且block为非空时再返回。
if(self.hitOnOffLineTime > 0)
{
if(self.offLineSuccessBlock != nil)
{
if ([NSThread isMainThread])
{
if(self.offLineSuccessBlock != nil)
{
self.offLineSuccessBlock(YES);
}
self.hitOnOffLineTime = 0;
}
else
{
dispatch_sync(dispatch_get_main_queue(), ^{
if (self.hitOnOffLineTime > 0)
{
if(self.offLineSuccessBlock != nil)
{
self.offLineSuccessBlock(YES);
}
self.hitOnOffLineTime = 0;
}
});
}
}
else
{
self.hitOnOffLineTime = 0;
}
}
第六个问题:
创建一个线程,在这个线程体内开始部分立刻起了一个线程。引起系统崩溃。
解决方案:
禁止这种无等待连环起线程的错误行为。

0 0
原创粉丝点击