异常日志记录 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:@"

*************************exception begin
exception time: %@
%@
*************************exception end

",[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了的。

原文地址:https://www.cnblogs.com/zhidao-chen/p/3583690.html