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

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

众所周知系统级崩溃定位不到代码的具体函数,一般都是内存释放时异常,空指针,越界访问问题。再加上苹果应用在切换到后台,杀线程问题,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];
});
}

第二个问题:

应用启动启动期间,调用了 dispatch_sync回主线程而引起崩溃。注意:app启动时,[NSThread isMainThread]判断是在子线程,也不能会主线程,不然崩溃。

当应用启后,不能在主线程里刷新UI。

方案:

在应用启动后判断是否在主线程,返回主线程。但是在应用启动过程中,禁止使用回主线程。

// this makes sure the change notification happens on the MAIN THREAD
if ([NSThread isMainThread])
{
}
else
{
dispatch_sync(dispatch_get_main_queue(), ^{
});
}

第三个问题:

在页面控制器中注册了通知,离开页面(不再重用)并期望销毁页面(使用不当导致实际上没有销毁页面,如:常规使用定时器),没有移除通知。当再次申请相同的页面时,有概率性出现通知相关的崩溃。

这个问题是困惑了我们几年的问题,大都报通知事件没有注册。崩溃栈指向的代码都是很正常的代码。这个问题我们最近两个月才发现这个根本原因。若你的技术水平做不到能真正的销毁页面,就在离开页面就移除通知。页面销毁时调用- (void)dealloc函数。只要你使用定时器,不特别处理,就是你把定时器指针置为nil,所在页面也销毁不了。所以实时移除注册的通知很有必要,也最简单。

解决方案:

离开页面就移除通知。若有特别的页面离开后,可能监控通知,自己特别处理,保证它真的不再使用时,在适当时候移除通知。


第四个问题:

在子线程里发送通知,在通知处理函数中不会主线程直接刷新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为非空时再返回。

i

f(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;
}
}

第六个问题:

创建一个线程,在这个线程体内开始部分立刻起了一个线程。文件描述符耗尽,引起系统崩溃。

解决方案:

禁止这种无等待连环起线程的错误行为。

第七个问题:

插入一个空对象到可变数组,或初始化数组是的元素为nil.

如下崩溃:

ModalName: 文件日志, ErrorLevel: Error, Function: UncaughtExceptionHandler, Line: 215, Format: <- 2017-03-31 11:02:48 ->[ Uncaught Exception ]
Name: NSInvalidArgumentException, Reason: *** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[0]
[ Fe Symbols Start ]
0   CoreFoundation                      0x000000018894eff0 <redacted> + 148
1   libobjc.A.dylib                     0x00000001873b0538 objc_exception_throw + 56
2   CoreFoundation                      0x00000001888302c8 <redacted> + 308
3   CoreFoundation                      0x0000000188942c38 <redacted> + 36
4   CoreFoundation                      0x0000000188832cbc <redacted> + 36
5   OutdoorClub                         0x0000000100133d58 -[ODCCurrentPathLocationDataSingleObject saveCoordateWithFileName:lastLocationOperateModel:] + 308
6   OutdoorClub                         0x0000000100132c90 -[ODCCurrentPathLocationDataSingleObject readmis] + 1672
7   OutdoorClub                         0x0000000100132324 __50-[ODCCurrentPathLocationDataSingleObject initData]_block_invoke + 100
8   OutdoorClub                         0x00000001003c2a10 +[NSTimer(YYAdd) _yy_ExecBlock:] + 148
9   Foundation                          0x0000000189443760 __NSFireTimer + 88
10  CoreFoundation                      0x00000001888fda9c <redacted> + 28
11  CoreFoundation                      0x00000001888fd7a0 <redacted> + 856
12  CoreFoundation                      0x00000001888fd060 <redacted> + 244
13  CoreFoundation                      0x00000001888fac84 <redacted> + 1484
14  CoreFoundation                      0x000000018882ad94 CFRunLoopRunSpecific + 424
15  GraphicsServices                    0x000000018a294074 GSEventRunModal + 100
16  UIKit                               0x000000018eae3130 UIApplicationMain + 208
17  OutdoorClub                         0x000000010014853c main + 124
18  libdyld.dylib                       0x000000018783959c <redacted> + 4
[ Fe Symbols End ]

引起崩溃的代码:

这个是上面调用的代码

[self.currentPathLocationDataArray addObject:self.locationOperateModel];
[self saveCoordateWithFileName:ODCCoordatesFileName lastLocationOperateModel:self.currentPathLocationDataArray[self.currentPathLocationDataArray.count-1]];

这个是崩溃的代码。

NSMutableArray *arr = [NSMutableArray arrayWithObject:lastLocationOperateModel];

它是怎么崩溃的呢?因为self.currentPathLocationDataArray为nil,加入的对象,再取出,当然还是nil了,你再初始化数组当然就崩溃了。
修改方法:
if(self.currentPathLocationDataArray == nil)
{
    self.currentPathLocationDataArray = [NSMutableArray array];
}
[self.currentPathLocationDataArray addObject:self.locationOperateModel];
目录
相关文章
|
缓存 JavaScript
vue阻止浏览器刷新和关闭页面提示
使用场景:在使用vuex进行缓存管理时,页面的缓存会随着页面关闭而消失,如果缓存动作仍在进行中,关闭页面会导致数据丢失,此时需要阻止页面关闭
1922 3
|
JSON JavaScript Linux
【MCP教程系列】Node.js+TypeScript搭建NPX MCP服务并自定义部署至阿里云百炼
本文介绍如何将阿里云百炼的工作流封装成MCP服务并部署,随后引入到智能体中使用。主要步骤包括:1) 封装MCP服务;2) 发布到npm官方平台;3) 在阿里云百炼平台创建自定义MCP服务;4) 在智能体中添加自定义MCP服务。通过这些步骤,用户可以轻松将工作流转化为MCP服务,并在智能体中调用。
4414 0
|
前端开发 小程序 API
uni-app 微信小程序中如何通过 canvas 画布实现电子签名?
uni-app 微信小程序中如何通过 canvas 画布实现电子签名?
uni-app 微信小程序中如何通过 canvas 画布实现电子签名?
|
前端开发 JavaScript 开发者
qiankun(乾坤)微前端框架简介
qiankun(乾坤)微前端框架简介
3816 1
|
前端开发
如何在Promise链中处理Promise.reject()抛出的错误?
如何在Promise链中处理Promise.reject()抛出的错误?
850 154
|
存储 编解码 前端开发
React 视频上传组件 Video Upload
随着互联网的发展,视频内容在网站和应用中愈发重要。本文探讨如何使用React构建高效、可靠的视频上传组件,涵盖基础概念、常见问题及解决方案。通过React的虚拟DOM和组件化开发模式,实现文件选择、进度显示、格式验证等功能,并解决跨域请求、并发上传等易错点。提供完整代码案例,确保用户能顺畅上传视频。
654 92
|
Ubuntu 关系型数据库 MySQL
Ubuntu 中apt 安装MySQL数据库
Ubuntu 中apt 安装MySQL数据库
655 0
|
存储 开发工具 数据安全/隐私保护
git报错The project you were looking for could not be found 解决方式
git报错The project you were looking for could not be found 解决方式
4383 1
|
前端开发 JavaScript 程序员
后端程序员的前端捷径-超级容易上手使用的前端框架layUI(上)
后端程序员的前端捷径-超级容易上手使用的前端框架layUI
1148 10