iOS 拦截崩溃处理

来源:互联网 发布:时间轴画图软件 编辑:程序博客网 时间:2024/05/27 14:14

ios app一旦提交就很难在对源进行线上修改 所以关键就是少出错少崩溃。 下面介绍一下崩溃拦截处理 可以用于崩溃日记收集 和 提高用户体验

  1. 首先在AppDelegate.m的- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions ;方法里,添加这句代码:InstallUncaughtExceptionHandler();// 拦截崩溃.当然,这个也可以在你建立好崩溃拦截的类后来添加.都是一样的.

生成一个继承于NSObject的类, .h文件里写上下面这些就够了.h 文件代码:

import <Foundation/Foundation.h>

import <UIKit/UIKit.h>

@interface UncaughtExceptionHandler : NSObject{BOOL dismissed;}@endvoid HandleException(NSException *exception);void SignalHandler(int signal);void InstallUncaughtExceptionHandler(void);

然后就是核心代码了,.会为你一一呈现.m 文件代码:

import "UncaughtExceptionHandler.h"

include <libkern/OSAtomic.h>

include <execinfo.h>

NSString *const UncaughtExceptionHandlerSignalExceptionName =@"UncaughtExceptionHandlerSignalExceptionName";NSString *const UncaughtExceptionHandlerSignalKey =@"UncaughtExceptionHandlerSignalKey";NSString *const UncaughtExceptionHandlerAddressesKey =@"UncaughtExceptionHandlerAddressesKey";

volatile int32_t UncaughtExceptionCount =0;const int32_t UncaughtExceptionMaximum =10;

const NSInteger UncaughtExceptionHandlerSkipAddressCount =4;const NSInteger UncaughtExceptionHandlerReportAddressCount =5;

@implementation UncaughtExceptionHandler

// 程序崩溃2(程序崩溃第二步走的方法)

  • (NSArray )backtrace {void callstack[128];int frames =backtrace(callstack, 128);char **strs =backtrace_symbols(callstack, frames);int i;NSMutableArray *backtrace = [NSMutableArray arrayWithCapacity:frames];for (i = UncaughtExceptionHandlerSkipAddressCount ; i <UncaughtExceptionHandlerSkipAddressCount +UncaughtExceptionHandlerReportAddressCount; i++){[backtrace addObject:[NSString stringWithUTF8String:strs[i]]];}free(strs);return backtrace;}
  • (void)alertView:(UIAlertView *)anAlertView clickedButtonAtIndex:(NSInteger)anIndex {if (anIndex ==0){dismissed =YES;}else if (anIndex==1) {NSLog(@"ssssssss");}}
  • (void)validateAndSaveCriticalApplicationData {// 崩溃拦截可以做的事,写在这个方法也是极好的}// 程序崩溃3(程序崩溃是第三进入的方法)
  • (void)handleException:(NSException *)exception {[self validateAndSaveCriticalApplicationData];

//这里可以打印或者显示出ERROR的原因.// NSString *message = [NSString stringWithFormat:NSLocalizedString(@"如果点击继续,程序有可能会出现其他的问题,建议您还是点击退出按钮并重新打开"@"异常原因如下:\n%@\n%@",nil),[exception reason],[[exception userInfo] objectForKey:UncaughtExceptionHandlerAddressesKey]];

//设置弹出框来了提醒用户, 当然也可以是自己设计其他内容,NSString *message = [NSString stringWithFormat:NSLocalizedString(@"如果点击继续,程序有可能会出现其他的问题,建议您还是点击退出按钮并重新打开",nil)];UIAlertView *alert =[[UIAlertView alloc]initWithTitle:NSLocalizedString(@"抱歉,程序出现了异常",nil)message:messagedelegate:selfcancelButtonTitle:NSLocalizedString(@"继续",nil)otherButtonTitles:NSLocalizedString(@"退出",nil), nil];[alert show];

// 利用RunLoop , 来完成拦截的操作CFRunLoopRef runLoop = CFRunLoopGetCurrent();CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);

while (!dismissed) {    for (NSString *mode in (__bridge NSArray *)allModes) {        CFRunLoopRunInMode((CFStringRef)mode,0.001, false);    }}CFRelease(allModes);NSSetUncaughtExceptionHandler(NULL);signal(SIGABRT,SIG_DFL);signal(SIGILL,SIG_DFL);signal(SIGSEGV,SIG_DFL);signal(SIGFPE,SIG_DFL);signal(SIGBUS,SIG_DFL);signal(SIGPIPE,SIG_DFL);[exception raise];if ([[exception name] isEqual:UncaughtExceptionHandlerSignalExceptionName]) {    kill(getpid(), [[[exception userInfo] objectForKey:UncaughtExceptionHandlerSignalKey]intValue]);}else{    [exception raise];}

}

@end
// 程序崩溃时1(程序崩溃是首先进入的方法, 你可以debug自己调试)
void HandleException(NSException *exception) {
int32_t exceptionCount =OSAtomicIncrement32(&UncaughtExceptionCount);
if (exceptionCount >UncaughtExceptionMaximum) {
return;
}

NSArray *callStack = [UncaughtExceptionHandler backtrace];NSMutableDictionary *userInfo =[NSMutableDictionary dictionaryWithDictionary:[exception userInfo]];[userInfo setObject:callStack forKey:UncaughtExceptionHandlerAddressesKey];[[[UncaughtExceptionHandler alloc] init]performSelectorOnMainThread:@selector(handleException:)withObject: [NSException exceptionWithName:[exception name] reason:[exception reason] userInfo:userInfo]waitUntilDone:YES];

}

void SignalHandler(int signal) {
int32_t exceptionCount =OSAtomicIncrement32(&UncaughtExceptionCount);
if (exceptionCount >UncaughtExceptionMaximum) {
return;
}

NSMutableDictionary *userInfo =[NSMutableDictionary dictionaryWithObject:[NSNumber numberWithInt:signal] forKey:UncaughtExceptionHandlerSignalKey];NSArray *callStack = [UncaughtExceptionHandler backtrace];[userInfo setObject:callStack forKey:UncaughtExceptionHandlerAddressesKey];[[[UncaughtExceptionHandler alloc] init] performSelectorOnMainThread:@selector(handleException:)withObject:[NSException exceptionWithName:UncaughtExceptionHandlerSignalExceptionName reason:[NSString stringWithFormat:NSLocalizedString(@"Signal %d was raised.",nil),signal]userInfo:                                                                                                          [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:signal]forKey:UncaughtExceptionHandlerSignalKey]]waitUntilDone:YES];

}

//. 进入程序时(在AppDelegate.m)里添加那行代码后,就会启用这行代码了
void InstallUncaughtExceptionHandler(void) {

NSSetUncaughtExceptionHandler(&HandleException);signal(SIGHUP, SignalHandler); signal(SIGINT, SignalHandler);signal(SIGQUIT, SignalHandler);signal(SIGABRT,SignalHandler);signal(SIGILL,SignalHandler);signal(SIGSEGV,SignalHandler);signal(SIGFPE,SignalHandler);signal(SIGBUS,SignalHandler);signal(SIGPIPE,SignalHandler);

}
//好啦,这些就完全够了,当你的程序遇到崩溃的时候, 就会稳稳的跳出提示信息, 继续就真的崩溃的, 退出就不会进行下一步操作了.还有一点要注意,当你连到真机上测试的时候,这个崩溃只会提示一次,你再次点击的时候他就不弹出提示而是直接崩溃了,所以你要是测试的话,把程序运行后, 拔掉真机, 不要连接电脑就可以了.




阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 与母亲的乱 诱人的母亲 母亲全集 同学的母亲 高傲的母亲 祝母亲生日快乐的话暖心 母亲心 母亲的心 母亲的心阅读答案 给母亲的一句暖心话 写给母亲暖心的句子 母亲写给孩子的暖心句子 8个字的暖心句子给母亲 故事母亲的心 机器之心第一季 心一 父亲草原母亲河原唱 母亲河 父亲的草原母亲的河歌词 父亲的草原母亲的河简谱 父亲草原母亲的河简谱 父亲草原母亲的河歌词 保护母亲河 黄河母亲河 母亲河入什么海 中国的母亲河 父亲的草原母亲的河萨克斯谱 关于母亲河的诗词 保护母亲河绘画图片 父亲的草原母亲的河歌谱 父亲的草原母亲的河banzou 父亲的草原母亲的河铃声下载 母亲河画 母亲河是什么河 我国的母亲河是 父亲的草原母亲的河腾格尔 保护母亲河的宣传语 中国的母亲河是什么河 父亲草原母亲河简谱3 父亲山母亲河简谱 走过母亲河