在我们实际开发中,我们会碰到很多的问题。但是闪退是我们和用户是最不能接受的,可我们打包之后没有办法获取到错误日志,所以在这里,我们将学习怎么在程序里获取错误日志,并且上传至我们规定的邮箱里面。
首先,我们先创建一个可以获取错误日志的类继承NSObject
CatchCrash
在这个类的.h里面定义一个可以获取错误日志的
void uncaughtExceptionHandler(NSException *exception);
在.m里面写具体的实现方法
// 异常的堆栈信息
NSArray *stackArray = [exception callStackSymbols];
// 出现异常的原因
NSString *reason = [exception reason];
// 异常名称
NSString *name = [exception name];
NSString *exceptionInfo = [NSStringstringWithFormat:@"Exception reason:%@\nException name:%@\nException stack:%@",name, reason, stackArray];
NSLog(@"%@", exceptionInfo);
NSMutableArray *tmpArr = [NSMutableArrayarrayWithArray:stackArray];
[tmpArr insertObject:reason atIndex:0];
//保存到本地 -- 当然你可以在下次启动的时候,上传这个log
[exceptionInfo writeToFile:[NSStringstringWithFormat:@"%@/Documents/error.log",NSHomeDirectory()] atomically:YESencoding:NSUTF8StringEncodingerror:nil];
//在出现错误的地方截图
UIGraphicsBeginImageContextWithOptions(CGSizeMake(CGRectGetWidth([UIScreenmainScreen].bounds),CGRectGetHeight([UIScreenmainScreen].bounds)),NO,1);
[[UIApplicationsharedApplication].keyWindowdrawViewHierarchyInRect:CGRectMake(0,0,CGRectGetWidth([UIScreenmainScreen].bounds),CGRectGetHeight([UIScreenmainScreen].bounds))afterScreenUpdates:NO];
UIImage *snapshot =UIGraphicsGetImageFromCurrentImageContext();
//把出现错误的截图保存在本地
[UIImageJPEGRepresentation(snapshot,1.0)writeToFile:[[NSStringalloc]initWithFormat:@"%@/Documents/bug.jpg",NSHomeDirectory()]atomically:YES];
UIGraphicsEndImageContext();
具体的文件
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface CatchCrash : NSObject
void uncaughtExceptionHandler(NSException *exception);
@end
#import "CatchCrash.h"
@implementation CatchCrash
void uncaughtExceptionHandler(NSException *exception)
{
// 异常的堆栈信息
NSArray *stackArray = [exception callStackSymbols];
// 出现异常的原因
NSString *reason = [exception reason];
// 异常名称
NSString *name = [exception name];
NSString *exceptionInfo = [NSStringstringWithFormat:@"Exception reason:%@\nException name:%@\nException stack:%@",name, reason, stackArray];
NSLog(@"%@", exceptionInfo);
NSMutableArray *tmpArr = [NSMutableArrayarrayWithArray:stackArray];
[tmpArr insertObject:reason atIndex:0];
//保存到本地 -- 当然你可以在下次启动的时候,上传这个log
[exceptionInfo writeToFile:[NSStringstringWithFormat:@"%@/Documents/error.log",NSHomeDirectory()] atomically:YESencoding:NSUTF8StringEncodingerror:nil];
//在出现错误的地方截图
UIGraphicsBeginImageContextWithOptions(CGSizeMake(CGRectGetWidth([UIScreenmainScreen].bounds),CGRectGetHeight([UIScreenmainScreen].bounds)),NO,1);
[[UIApplicationsharedApplication].keyWindowdrawViewHierarchyInRect:CGRectMake(0,0,CGRectGetWidth([UIScreenmainScreen].bounds),CGRectGetHeight([UIScreenmainScreen].bounds))afterScreenUpdates:NO];
UIImage *snapshot =UIGraphicsGetImageFromCurrentImageContext();
//把出现错误的截图保存在本地
[UIImageJPEGRepresentation(snapshot,1.0)writeToFile:[[NSStringalloc]initWithFormat:@"%@/Documents/bug.jpg",NSHomeDirectory()]atomically:YES];
UIGraphicsEndImageContext();
return;
}
@end
NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
NSString *str = [[NSStringalloc]initWithContentsOfFile:[[NSStringalloc]initWithFormat:@"%@/Documents/error.log",NSHomeDirectory()]encoding:NSUTF8StringEncodingerror:nil];
if (str)
{
有错误需要执行的
}
else
{
没有错误需要执行的
}
之后就是我们怎么上传到邮箱里
NSString *str = [[NSStringalloc]initWithContentsOfFile:[[NSStringalloc]initWithFormat:@"%@/Documents/error.log",NSHomeDirectory()]encoding:NSUTF8StringEncodingerror:nil];
MFMailComposeViewController *mc = [[MFMailComposeViewControlleralloc]init];
mc.mailComposeDelegate =self;
if (!mc)
{
// UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"请先添加邮箱账户" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
// [alert show];
return;
}
[mc setSubject:@"错误日志"];
[mc setToRecipients:[[NSArrayalloc]initWithObjects:@"455166565@qq.com",nil]];
[mc setMessageBody:str isHTML:NO];
[mc addAttachmentData:[NSDatadataWithContentsOfFile:[[NSStringalloc]initWithFormat:@"%@/Documents/bug.jpg",NSHomeDirectory()]]mimeType:@""fileName:@"bug.jpg"];
[selfpresentViewController:mcanimated:YEScompletion:nil];
这是系统提供的一个发送邮件的一个类需要导入MessageUI.framework
在我们的代理方法里面需要做一些操作
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(nullableNSError *)error
{
switch (result)
{
caseMFMailComposeResultCancelled:
NSLog(@"Mail send canceled...");
break;
caseMFMailComposeResultSaved:
NSLog(@"Mail saved...");
break;
caseMFMailComposeResultSent:
[[NSFileManagerdefaultManager]removeItemAtPath:[NSStringstringWithFormat:@"%@/Documents/error.log",NSHomeDirectory()]error:nil];
[[NSFileManagerdefaultManager]removeItemAtPath:[[NSStringalloc]initWithFormat:@"%@/Documents/bug.jpg",NSHomeDirectory()]error:nil];
NSLog(@"Mail sent...");
break;
caseMFMailComposeResultFailed:
NSLog(@"Mail send errored: %@...", [errorlocalizedDescription]);
break;
default:
break;
}
[selfdismissViewControllerAnimated:YEScompletion:nil];
}
这里删除错误文件看项目需求,在哪里打开邮箱并上传也需要看实际需要。
这里我们的错误日志获取,上传至邮箱完成了
最后附上demo的下载地址 http://download.csdn.net/detail/a174455171/9514511
关于上次我写的做一些补充。
这个方法只能获取到OC的异常,其他的还需要各位在网上搜其他的方法
在注册捕获异常的时候尽量写到
didFinishLaunchingWithOptions最后,因为第三方的SDK有时候会把你的权限截获