iOS 崩溃信息拦截防止闪退
2016-06-07 17:37
465 查看
//____________________.h_____________________________
#import<Foundation/Foundation.h>
#import
<UIKit/UIKit.h>
@interface UncaughtExceptionHandler :NSObject{
BOOL dismissed;
}
@end
void 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";
volatileint32_t UncaughtExceptionCount =0;
constint32_t UncaughtExceptionMaximum =10;
constNSInteger UncaughtExceptionHandlerSkipAddressCount =4;
constNSInteger UncaughtExceptionHandlerReportAddressCount =5;
@implementation UncaughtExceptionHandler
+ (NSArray *)backtrace {
void* callstack[128];
int frames =backtrace(callstack,
128);
char **strs =backtrace_symbols(callstack, frames);
int i;
NSMutableArray *backtrace = [NSMutableArrayarrayWithCapacity:frames];
for (i = UncaughtExceptionHandlerSkipAddressCount ; i <UncaughtExceptionHandlerSkipAddressCount
+UncaughtExceptionHandlerReportAddressCount; i++){
[backtraceaddObject:[NSStringstringWithUTF8String:strs[i]]];
}
free(strs);
return backtrace;
}
- (void)alertView:(UIAlertView *)anAlertView clickedButtonAtIndex:(NSInteger)anIndex
{
if (anIndex ==0){
dismissed =YES;
}elseif (anIndex==1) {
NSLog(@"ssssssss");
}
}
- (void)validateAndSaveCriticalApplicationData {
}
- (void)handleException:(NSException *)exception {
[selfvalidateAndSaveCriticalApplicationData];
NSString *message = [NSStringstringWithFormat:NSLocalizedString(@"如果点击继续,程序有可能会出现其他的问题,建议您还是点击退出按钮并重新打开\n\n"@"异常原因如下:\n%@\n%@",nil),[exceptionreason],[[exceptionuserInfo]
objectForKey:UncaughtExceptionHandlerAddressesKey]];
UIAlertView *alert =[[UIAlertViewalloc]initWithTitle:NSLocalizedString(@"抱歉,程序出现了异常",nil)
message:message
delegate:self
cancelButtonTitle:NSLocalizedString(@"退出",nil)
otherButtonTitles:NSLocalizedString(@"继续",nil),
nil];
[alert show];
CFRunLoopRef runLoop = CFRunLoopGetCurrent();
CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);
while (!dismissed) {
for (NSString *modein
(__bridgeNSArray *)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);
if ([[exception
name] isEqual:UncaughtExceptionHandlerSignalExceptionName]) {
kill(getpid(), [[[exceptionuserInfo]
objectForKey:UncaughtExceptionHandlerSignalKey]intValue]);
}else{
[exception
raise];
}
}
@end
void HandleException(NSException *exception) {
int32_t exceptionCount =OSAtomicIncrement32(&UncaughtExceptionCount);
if (exceptionCount >UncaughtExceptionMaximum) {
return;
}
NSArray *callStack = [UncaughtExceptionHandlerbacktrace];
NSMutableDictionary *userInfo =[NSMutableDictionarydictionaryWithDictionary:[exceptionuserInfo]];[userInfo
setObject:callStack
forKey:UncaughtExceptionHandlerAddressesKey];
[[[UncaughtExceptionHandleralloc]
init]performSelectorOnMainThread:@selector(handleException:)withObject:
[NSExceptionexceptionWithName:[exceptionname]
reason:[exceptionreason]
userInfo:userInfo]waitUntilDone:YES];
}
void SignalHandler(int signal) {
int32_t exceptionCount =OSAtomicIncrement32(&UncaughtExceptionCount);
if (exceptionCount >UncaughtExceptionMaximum) {
return;
}
NSMutableDictionary *userInfo =[NSMutableDictionarydictionaryWithObject:[NSNumbernumberWithInt:signal]
forKey:UncaughtExceptionHandlerSignalKey];
NSArray *callStack = [UncaughtExceptionHandlerbacktrace];[userInfo
setObject:callStackforKey:UncaughtExceptionHandlerAddressesKey];
[[[UncaughtExceptionHandleralloc]
init]performSelectorOnMainThread:@selector(handleException:)withObject:[NSExceptionexceptionWithName:UncaughtExceptionHandlerSignalExceptionNamereason:[NSStringstringWithFormat:NSLocalizedString(@"Signal
%d was raised.",nil),signal]userInfo:
[NSDictionarydictionaryWithObject:[NSNumbernumberWithInt:signal]forKey:UncaughtExceptionHandlerSignalKey]]waitUntilDone:YES];
}
void InstallUncaughtExceptionHandler(void) {
NSSetUncaughtExceptionHandler(&HandleException);
signal(SIGABRT,SignalHandler);
signal(SIGILL,SignalHandler);
signal(SIGSEGV,SignalHandler);
signal(SIGFPE,SignalHandler);
signal(SIGBUS,SignalHandler);
signal(SIGPIPE,SignalHandler);
}
//_________________调用_________________
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary
*)launchOptions {
InstallUncaughtExceptionHandler();
return YES;
}
#import<Foundation/Foundation.h>
#import
<UIKit/UIKit.h>
@interface UncaughtExceptionHandler :NSObject{
BOOL dismissed;
}
@end
void 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";
volatileint32_t UncaughtExceptionCount =0;
constint32_t UncaughtExceptionMaximum =10;
constNSInteger UncaughtExceptionHandlerSkipAddressCount =4;
constNSInteger UncaughtExceptionHandlerReportAddressCount =5;
@implementation UncaughtExceptionHandler
+ (NSArray *)backtrace {
void* callstack[128];
int frames =backtrace(callstack,
128);
char **strs =backtrace_symbols(callstack, frames);
int i;
NSMutableArray *backtrace = [NSMutableArrayarrayWithCapacity:frames];
for (i = UncaughtExceptionHandlerSkipAddressCount ; i <UncaughtExceptionHandlerSkipAddressCount
+UncaughtExceptionHandlerReportAddressCount; i++){
[backtraceaddObject:[NSStringstringWithUTF8String:strs[i]]];
}
free(strs);
return backtrace;
}
- (void)alertView:(UIAlertView *)anAlertView clickedButtonAtIndex:(NSInteger)anIndex
{
if (anIndex ==0){
dismissed =YES;
}elseif (anIndex==1) {
NSLog(@"ssssssss");
}
}
- (void)validateAndSaveCriticalApplicationData {
}
- (void)handleException:(NSException *)exception {
[selfvalidateAndSaveCriticalApplicationData];
NSString *message = [NSStringstringWithFormat:NSLocalizedString(@"如果点击继续,程序有可能会出现其他的问题,建议您还是点击退出按钮并重新打开\n\n"@"异常原因如下:\n%@\n%@",nil),[exceptionreason],[[exceptionuserInfo]
objectForKey:UncaughtExceptionHandlerAddressesKey]];
UIAlertView *alert =[[UIAlertViewalloc]initWithTitle:NSLocalizedString(@"抱歉,程序出现了异常",nil)
message:message
delegate:self
cancelButtonTitle:NSLocalizedString(@"退出",nil)
otherButtonTitles:NSLocalizedString(@"继续",nil),
nil];
[alert show];
CFRunLoopRef runLoop = CFRunLoopGetCurrent();
CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);
while (!dismissed) {
for (NSString *modein
(__bridgeNSArray *)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);
if ([[exception
name] isEqual:UncaughtExceptionHandlerSignalExceptionName]) {
kill(getpid(), [[[exceptionuserInfo]
objectForKey:UncaughtExceptionHandlerSignalKey]intValue]);
}else{
[exception
raise];
}
}
@end
void HandleException(NSException *exception) {
int32_t exceptionCount =OSAtomicIncrement32(&UncaughtExceptionCount);
if (exceptionCount >UncaughtExceptionMaximum) {
return;
}
NSArray *callStack = [UncaughtExceptionHandlerbacktrace];
NSMutableDictionary *userInfo =[NSMutableDictionarydictionaryWithDictionary:[exceptionuserInfo]];[userInfo
setObject:callStack
forKey:UncaughtExceptionHandlerAddressesKey];
[[[UncaughtExceptionHandleralloc]
init]performSelectorOnMainThread:@selector(handleException:)withObject:
[NSExceptionexceptionWithName:[exceptionname]
reason:[exceptionreason]
userInfo:userInfo]waitUntilDone:YES];
}
void SignalHandler(int signal) {
int32_t exceptionCount =OSAtomicIncrement32(&UncaughtExceptionCount);
if (exceptionCount >UncaughtExceptionMaximum) {
return;
}
NSMutableDictionary *userInfo =[NSMutableDictionarydictionaryWithObject:[NSNumbernumberWithInt:signal]
forKey:UncaughtExceptionHandlerSignalKey];
NSArray *callStack = [UncaughtExceptionHandlerbacktrace];[userInfo
setObject:callStackforKey:UncaughtExceptionHandlerAddressesKey];
[[[UncaughtExceptionHandleralloc]
init]performSelectorOnMainThread:@selector(handleException:)withObject:[NSExceptionexceptionWithName:UncaughtExceptionHandlerSignalExceptionNamereason:[NSStringstringWithFormat:NSLocalizedString(@"Signal
%d was raised.",nil),signal]userInfo:
[NSDictionarydictionaryWithObject:[NSNumbernumberWithInt:signal]forKey:UncaughtExceptionHandlerSignalKey]]waitUntilDone:YES];
}
void InstallUncaughtExceptionHandler(void) {
NSSetUncaughtExceptionHandler(&HandleException);
signal(SIGABRT,SignalHandler);
signal(SIGILL,SignalHandler);
signal(SIGSEGV,SignalHandler);
signal(SIGFPE,SignalHandler);
signal(SIGBUS,SignalHandler);
signal(SIGPIPE,SignalHandler);
}
//_________________调用_________________
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary
*)launchOptions {
InstallUncaughtExceptionHandler();
return YES;
}
相关文章推荐
- iOS CoreAnimation专题——原理篇(四)动画时间控制
- iOS开发拓展篇—CoreLocation定位服务
- ios一步一步编译ffmpeg,x264实现h264编码
- iOS 内存泄漏整理
- IOS开发-XCode常用快捷键整理
- iOS 聊天信息图文混排
- 分享iOS中常用的绘图, 截屏方法
- iOS FMDB
- iOS总结_IOS开发部分语法的简化写法
- IOS项目流水线开发步骤(初稿)
- iOS 开发之照片框架详解
- iOS 保持界面流畅的技巧(AsyncDisplayKit)
- iOS实现头像选取(照相或者图片库)、大小等比缩放、生成圆形头像 (转载,已验证可以)
- iOS 程序启动的顺序
- iOS开发--PickView 选取器笔记
- iOS 多线程--(GCD)
- IOS7笔记- 7、视图、绘制、手势识别
- iOS10个实用小技巧(总有你不知道的和你会用到的)
- iOS多线程小结( NSOperation)
- Masonry教程--IOS自适配,丢掉Autolayout吧