在写代码之前,我们先弄明白一个app运行的流程。
程序运行启动时依次调用
1.启动页先运行
2.- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
3.- (void)applicationDidBecomeActive:(UIApplication*)application
程序退到后台依次调用
1.- (void)applicationWillResignActive:(UIApplication*)application
2.- (void)applicationDidEnterBackground:(UIApplication*)application
程序从后台回到前台依次调用
1.- (void)applicationWillEnterForeground:(UIApplication*)application
2.- (void)applicationDidBecomeActive:(UIApplication*)application
程序被手动杀掉会依次调用
// 双击home键 回到正在执行的app界面走这个回调
1.- (void)applicationWillResignActive:(UIApplication*)application
// 上移app手动杀掉后走下面两个回调
2.- (void)applicationDidEnterBackground:(UIApplication*)application
3.- (void)applicationWillTerminate:(UIApplication*)application
程序崩溃闪退和在后台被系统杀掉则不会调用任何方法
分析:我们需要记录程序崩溃的次数,手动杀掉程序和程序在后台被系统回收杀掉是不能统计的。如上所述流程里,程序崩溃不会执行任何回调,但是手动杀掉程序和程序在后台被系统回收杀掉都要先让程序回到后台,走- (void)applicationDidEnterBackground:(UIApplication*)application
这个回调。根据这个区别我们就可以来做一个崩溃的记录。
实现思路:在程序启动时把存储在沙盒中的崩溃标识JJ_isCrash置为YES,程序回到后台时把isCrash改为NO,程序回到前台时再把JJ_isCrash改为YES。
代码:
程序启动
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self recordCrashCount];
}
程序进入后台
- (void)applicationDidEnterBackground:(UIApplication*)application {
[[NSUserDefaults standardUserDefaults] setObject:@(NO) forKey:@"JJ_isCrash"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
程序回到前台
- (void)applicationWillEnterForeground:(UIApplication *)application {
[[NSUserDefaults standardUserDefaults] setObject:@(YES) forKey:@"JJ_isCrash"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
// 判断和记录崩溃的次数
- (void)recordCrashCount{
BOOL isCrash = [[[NSUserDefaults standardUserDefaults] valueForKey:@"JJ_isCrash"] boolValue];
[[NSUserDefaults standardUserDefaults] setObject:@(YES) forKey:@"JJ_isCrash"];
if (isCrash == YES) {
//获取到本地存储的崩溃次数
NSNumber *crashNum = [[NSUserDefaults standardUserDefaults] valueForKey:@"JJ_crashCount"];
NSInteger count =0;
if (crashNum != nil) {
count = [crashNum integerValue];
}
count++;
//判断崩溃次数达到多少次时执行操作
if (count >= crashCount) {
NSLog(@"多次崩溃");
//将本地文件崩溃次数重新置为0
[[NSUserDefaults standardUserDefaults] setObject:@0 forKey:@"JJ_crashCount"];
// 5秒后执行弹窗警告操作
[self performSelector:@selector(showAlertAction)withObject:nil afterDelay:5];
return;
}
//崩溃次数未达到3次则向本地存储崩溃次数
crashNum = [NSNumber numberWithInteger:count];
[[NSUserDefaults standardUserDefaults] setObject:crashNum forKey:@"JJ_crashCount"];
}
}
// 弹出升级警告
- (void)showAlertAction{
UIAlertController*alert
=
[UIAlertControlleralertControllerWithTitle:@"警告"message:@"检测到软件多次异常退出,建议您尽快更新到最新版本!" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction*sure = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefaulthandler:nil];
[alert addAction:sure];
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
}
为了方便大家直接使用,我已经将实现代码封装为一个小框架,只需使用一句代码即可调用。
github下载地址: https://github.com/jiangbin1993/JJRecordCrash
使用方法:
在appdelegate.m中导入头文件 #import "JJRecordCrash.h"
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 参数crashCount为崩溃多少次后执行block中的代码
[[JJRecordCrash shareInstance] recordCrashWithCrashCount:2 handle:^{
// 多次崩溃后执行自己想执行的代码,如:清除缓存 提示用户更新
NSLog(@"崩溃啦");
}];
return YES;
}
注意:调试时,在程序运行中直接使用xcode重新运行程序,因为不会走- (void)applicationDidEnterBackground:(UIApplication*)application
方法,所以也相当于是崩溃,同样会被记录下来。
网友评论
当用户按下home键让程序进入后台时,如你所说调用- (void)applicationDidEnterBackground:(UIApplication*)application这个方法进入Background这个状态,之后程序会变为suspended状态被挂起,假设这时候系统因内存不足等原因杀掉程序时,程序是不会收到任何回调的,[[NSUserDefaults standardUserDefaults] setObject:@(NO) forKey:@"JJ_isCrash"]这行代码也无从调用,这样你是如何判断的呢。