异常日志记录 DDLog
项目中如果想把异常捕获再写入文件,有个十分容易使用的库DDLog.
首先导入库,在git上下载。
一:在项目初始化指定全局LogLeve ,一般在xxxapp.m中
staticconstint ddLogLevel = LOG_LEVEL_VERBOSE;
二:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { NSExceptionHandler *exceptionHandler = [NSExceptionHandler defaultExceptionHandler] ; exceptionHandler.delegate = self; exceptionHandler.exceptionHandlingMask = NSLogAndHandleEveryExceptionMask; DBSDDFileLogger *fileLogger = [[DBSDDFileLogger alloc] init]; fileLogger.maximumFileSize = 1; // 1024*1 KB fileLogger.rollingFrequency = 1; // 60*60*60 Seconds fileLogger.logFileManager.maximumNumberOfLogFiles = 4; [DDLog addLogger:fileLogger]; }
- (BOOL)exceptionHandler:(NSExceptionHandler *)sender shouldLogException:(NSException *)exception mask:(unsigned int)mask { [self printStackTrace:exception]; return YES; }
- (void)printStackTrace:(NSException *)e//要写入log文件的信息 { NSString *stack = [[e userInfo] objectForKey:NSStackTraceKey]; NSMutableArray *args = [NSMutableArray arrayWithCapacity:20]; if (stack) { NSTask *ls = [[NSTask alloc] init]; NSString *pid = [[NSNumber numberWithInt:[[NSProcessInfo processInfo] processIdentifier]] stringValue]; [args addObject:@"-p"];//-p [args addObject:pid]; [args addObjectsFromArray:[stack componentsSeparatedByString:@" "]]; // Note: function addresses are separated by double spaces, not a single space. [ls setLaunchPath:@"/usr/bin/atos"];//xcrun atos [ls setArguments:args]; // [ls launch]; NSPipe *pipe; pipe = [NSPipe pipe]; [ls setStandardOutput: pipe]; NSFileHandle *file; file = [pipe fileHandleForReading]; [ls launch]; NSData *data; data = [file readDataToEndOfFile]; NSString *string; string = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding]; NSString *strFormat = [NSString stringWithFormat:@"\n\n*************************exception begin\nexception time: %@\n%@\n*************************exception end\n\n",[NSDate date] ,string]; DDLogCError(strFormat); } else { DDLogCError(@"No stack trace available."); } }
三 。两个自定义类。这里的DBSDDFileLogger继承于DDFileLogger,目的在于自定义log文件的路径。如下:
#import "DBSDDFileLogger.h" #import "DBSDDLogFileManagerDefault.h" #define DBSLogDir @"DBstudio/Files/Logs" @implementation DBSDDFileLogger - (id)init{ DBSDDLogFileManagerDefault *defaultLogFileManager = [[DBSDDLogFileManagerDefault alloc] initWithLogsDirectory:[self getDBSCacheLogsDir]]; return [self initWithLogFileManager:defaultLogFileManager]; } - (NSString*)getDBSCacheLogsDir{ NSString *dir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)objectAtIndex:0]; NSString *cachedLogDir=[dir stringByAppendingPathComponent:DBSLogDir]; return cachedLogDir; }
DBSDDLogFileManagerDefault 继承自 DDLogFileManagerDefault 目的在于自定义log文件的路径
@implementation DBSDDLogFileManagerDefault - (NSString *)generateShortUUID{ NSDate *date = [[NSDate alloc] init]; NSDateFormatter *threadUnsafeDateFormatter = [[NSDateFormatter alloc] init]; [threadUnsafeDateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4]; NSString *dateFormatString = @"yyyy-MM-dd"; [threadUnsafeDateFormatter setDateFormat:dateFormatString]; NSString *filename = [threadUnsafeDateFormatter stringFromDate:date]; return filename; } - (NSString *)createNewLogFile{ NSString *logsDirectory = [self logsDirectory]; int index = 1; NSString *fileName = [NSString stringWithFormat:@"dbs-log-%@.txt", [self generateShortUUID]]; do { NSString *filePath = [logsDirectory stringByAppendingPathComponent:fileName]; if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) { [[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil]; // Since we just created a new log file, we may need to delete some old log files [super deleteOldLogFiles]; NSLog(@"create file:%@",fileName); return filePath; } else { NSString *strFile = [filePath stringByDeletingPathExtension]; NSString *strFileName = [strFile lastPathComponent]; NSString *strFileNameFormat = [self isContainCharacter:strFileName]; if (strFileNameFormat) { strFileName = strFileNameFormat; } fileName =[NSString stringWithFormat:@"%@(%d).%@",strFileName,index,[filePath pathExtension]]; index++; } } while(YES); } - (NSString*)isContainCharacter:(NSString*)fileName{ NSString *strCharachter = @"("; NSRange foundPer=[fileName rangeOfString:strCharachter options:NSCaseInsensitiveSearch]; if(foundPer.length>0) { NSRange rang; rang.location = 0; rang.length = foundPer.location; NSString *strRes = [fileName substringWithRange:rang]; return strRes; } else { return nil; } } - (BOOL)isLogFile:(NSString *)fileName{ if (fileName && [fileName length]>3) { NSRange rang; rang.location = [fileName length] - 4; rang.length = 4; NSString *strTmpName = [fileName substringWithRange:rang]; if ([strTmpName isEqualToString:@".txt"]) { rang.location = 0; rang.length = 4; strTmpName = [fileName substringWithRange:rang]; if ([@"dbs-" isEqualToString:strTmpName]) { return YES; } } } return NO; }
好了,test一下
- (IBAction)test:(id)sender { //@try { NSMutableArray *array = [NSMutableArray array]; [array addObject:nil]; //} //@catch (NSException *exception) { //@throw exception; //} //@finally { //} }
DDLogger比较强悍的地方是可以记录所有异常,包括你catch了的。