iphone闪退修复工具_解决APP连续闪退的方案

首先要检测用户 App 出现了连续闪退的情况,有两种检测方法,捕获异常和计时器。

1. 捕获异常

检测连续闪退,可以通过捕获异常来实现,异常有以下种类:

Mach 异常:EXC_CRASH

UNIX 信号:SIGABRT

NSException 异常:应用层,通过 NSUncaughtExceptionHandler 捕获

在念茜的漫谈 iOS Crash 收集框架一文中详细介绍了 Mach 异常和 Unix 信号捕获 crash 的机制。简单来说,异常一般产生自 iOS 的微内核 Mach,然后在 BSD 层转换成 UNIX SIGABRT 信号,以标准 POSIX 信号的形式提供给用户。NSException 是使用者在处理 App 逻辑时,用编程的方法抛出。

如何捕获异常

通过以下方法捕获异常:

利用 Mach API 捕获 Mach 异常

通过 POSIX API 注册 signal(SIGSEGV,signalHandler) 来捕获 UNIX 异常信号

注册 NSUncaughtExceptionHandler 来捕获应用级异常

Crash 上报工具如 PLCrashReporter 通过注册 Mach 异常 + UNIX信号 的 handler 达到检测的目的,对用户提供了处理异常的接口。

如何检测

可以利用 PLCrashReporter 这类工具来检测连续闪退:

首先维护一个计数变量,表示连续闪退次数

在 PLCrashReporter 的 crash handler 中加入逻辑:如果启动 5s 内 crash 使计数器加一

每次启动时,如果连续闪退计数 > n,则检测到了连续闪退

启动后,执行一个定时任务,在 5s 后重置计数(如果 App 连续闪退则不会重置)

f9b5e7f11889e6f7a82f2cb1964cd59e.png

流程图

优缺点

通过 Mach 异常、Unix 信号、NSException 异常来检测闪退,能获得更多的 crash 上下文,但由于 crash 收集框架多使用这些方法,可能会有这样的风险:与第三方 crash 收集框架冲突导致漏检测。另外,可能会与 App 已有的异常处理代码产生耦合。

2. 计时器方法

除了通过捕获异常的方式检测连续闪退,还可以通过计数器方法来检测:

维护一个计数变量,用于表示连续闪退的次数

在启动 application:didFinishLaunchingWithOptions: 后使计数加一

接着使用 dispatch_after 方法在 5s 后清零计数,如果 App 活不过 5 秒计数就不会被清零

如果发现计数变量 > n,表明 App 连续 n 次连续闪退,启动保护流程,重置计数。

当保护流程完成后,进入 App 正常启动流程

3de8c953a15b0570bb65471496880228.png

流程图

优缺点

而计数器方法逻辑简单,与原有的代码耦合小。虽然有误报可能(在启动后立即被 kill 掉,误认为 crash),但是可以通过设置阈值来减小误报的误报率。

综上权衡,我们使用计时器方法检测连续闪退。

连续闪退修复

检测到连续闪退后,接下来要尝试对闪退进行修复,这里先分析可能的闪退原因,再结合微信读书的例子说明修复流程。

闪退原因

连续闪退,可能是 App 启动关键路径中执行了必 crash 的代码,原因可能有:

数据库损坏:在日常使用如异常退出、断电,或者错误的操作(参考:sqlite corruption causes)。

文件损坏:处理文件时如果没有@try...catch,损坏文件会抛出NSException导致 crash

网络返回数据处理异常:比如预期返回数组,但实际返回了字典,对字典对象执行-objectAtIndex方法会产生crash: unknow selector send to object;,或返回破损的 Tar 包,在解压失败导致 crash。

代码 bug:当必 crash 的代码出现在启动关键路径中,就会导致连续闪退。

针对 1,可以通过工具修复数据库,或者删除 DB。针对2,可以删除文件来进行修复。对于 3 和 4,我们需要具体地分析 crash 案例,通过 JSPatch 来进行修复。

微信读书的修复流程

为了应对上述导致连续闪退的原因,微信读书的修复流程为:

进入 didFinishLaunch 时检查是否有连续闪退,无则执行 5

弹 Toast 提示用户是否修复,轻触『修复』执行2,否则执行 5

尝试下载并执行 JSPatch 补丁

这里是为了解决上述第4点 - 代码 bug 导致的闪退,使用 JSPatch[github]可以进行热修复。在 didFinishLaunching 时,会卡住界面发请求检查是否有可用的 JSPatch 脚本,如果有则加载执行,解决代码 bug 导致的闪退。

尝试删除Documents/Library/Caches目录下的所有文件

这里直接删除了所有用户数据,适用于微信读书这种所有数据都在云端,删除后可以完全从云端恢复。如果你的 App 不属于这种场景,那么应该在 repairBlock 中自定义修复逻辑,比如:

a. 不删除文件,只修复数据库

b. 修复前把用户数据备份到云端

c. 收集 crash 样本,查明原因,定制 JSPatch 修复补丁并下发

退出微信读书登录状态

进入原 didFinishLaunch

连续闪退检测 + 保护流程如图所示:

c66114db5570f5867d5b9f2872b6f58c.png

实现

检测和连续 crash 并修复需要修改原-application:didFinishLaunchingWithOptions:逻辑,有几种方法:

直接修改-application:didFinishLaunchingWithOptions:方法。

新建一个SubAppDelegate类来继承AppDelegate,覆盖-application:didFinishLaunchingWithOptions:方法,然后把main()函数中的AppDelegate替换为SubAppDelegate

新建一个AppDelegate扩展,然后用 method swizzle 的方法替换-application:didFinishLaunchingWithOptions:方法。

上述三种方案,对现有项目改动代价是 1 > 2 > 3。因此,我们使用对源码修改代价最小的方案 3 来替换-application:didFinishLaunchingWithOptions:。

检测的逻辑 GYBootingProtection 已经处理好,修复的处理预留了接口,可以由用户自定义,把自定义的修复流程传入 repairBlock 即可。

使用

引入项目

下载(github)源码 ,将src目录下所有文件拖拽到你的 Xcode 项目

在AppDelegate+GYBootingProtection.m的onBeforeBootingProtection方法中添加检测前需要执行的代码,比如设置crash上报:

- (void)onBeforeBootingProtection {

[GYBootingProtection setLogger:^(NSString*msg) {

// setup logger

NSLog(@"%@", msg);

}];

[GYBootingProtection setReportBlock:^(NSIntegercrashCounts) {

// setup crash report

}];

}

在onBootingProtection方法中添加修复逻辑,比如删除文件:

- (void)onBootingProtection {

// 检查 JSPatch 更新

...

// 删除 Documents Library Caches 目录下所有文件

[GYBootingProtection deleteAllFilesUnderDocumentsLibraryCaches];

...}

如需执行异步的修复逻辑,在onBootingProtectionWithCompletion:方法添加修复逻辑,并在完成修复后调用 completion :

- (void)onBootingProtectionWithCompletion:(BoolCompletionBlock)completion {

[selfonBootingProtection];

// 异步修复

[selfasyncRepairWithCompletion:^(void) {

// 正常启动流程

if(completion) completion();

}];

}

测试

首先制造连续闪退场景:

启动后 5 秒内,双击 Home 通过上划手势 kill 掉 App,重复多次。(也可以在代码里人为制造crash)

当连续闪退超过 5 次时,会提示用户修复:

7fa2d5ff4ae4822b23e9015ddb497cfc.png

用户轻触修复,App 重置初始状态,连续闪退问题解决!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值