iOS Swift Crash日志收集

尝试使用Swift进行日志收集-----------失败,最后还是调用OC实现

AppDelegate中

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        
        CatchCrash.share().installUncaughtExceptionHandler()
        
        return true
    }

 

CatchCrash.swift

import UIKit

private let catchCrash = CatchCrash()
private var UncaughtExceptionCount: Int32 = 0
private var UncaughtExceptionMaximum: Int32 = 10
class CatchCrash: NSObject {
    private let UncaughtExceptionMaximum: Int32 = 10

    private let SignalHandler: Darwin.sig_t? = { (signal) in
        let exceptionInfo = HandleCrash.crash(signal)
        try! exceptionInfo?.write(toFile: NSHomeDirectory() + "/Documents/error1.log", atomically: true, encoding: .utf8)
    }
    
    class func share() -> CatchCrash {
        return catchCrash
    }
    
    func installUncaughtExceptionHandler() {
        
        NSSetUncaughtExceptionHandler { (exception) in
            // 异常的堆栈信息
            let stackArray = exception.callStackSymbols
            
            // 出现异常的原因
            let reason = exception.reason
            
            // 异常名称
            let name = exception.name
            
            let exceptionInfo = "Eqqqqqxception reason:\(String(describing: reason))\n"
                + "Exception name:\(name)\n"
                + "Exception stack:\(stackArray.description)"
            
            print(exceptionInfo)
            
            var tmpArr = stackArray
            tmpArr.insert(reason!, at: 0)
            
            //保存到本地
            try! exceptionInfo.write(toFile: NSHomeDirectory() + "/Documents/error1.log", atomically: true, encoding: .utf8)
            abort()
        }
        
        signal(SIGABRT, SignalHandler)
        signal(SIGILL, SignalHandler)
        signal(SIGSEGV, SignalHandler)
        signal(SIGFPE, SignalHandler)
        signal(SIGBUS, SignalHandler)
        signal(SIGPIPE, SignalHandler)
    }
}

 CatchCrash-Bridging-Header.h 中进行桥接

#import "HandleCrash.h"

 HandleCrash.h

#import <Foundation/Foundation.h>

@interface HandleCrash : NSObject

+ (NSString *)crash:(int)signal;

@end

  HandleCrash.m

#import "HandleCrash.h"
#import <stdatomic.h>
#include <execinfo.h>

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

atomic_int UncaughtExceptionCount = 0;
const int32_t UncaughtExceptionMaximum = 10;

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

@implementation HandleCrash

+ (NSString *)crash:(int)signal {
    int exceptionCount = atomic_fetch_add_explicit(&UncaughtExceptionCount, 1,  memory_order_relaxed);
    if (exceptionCount > UncaughtExceptionMaximum) {
        return @"";
    }
    
    NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithObject:[NSNumber numberWithInt:signal]
                                                                       forKey:UncaughtExceptionHandlerSignalKey];
    NSArray *callStack = [self backtrace];
    [userInfo setObject:callStack
                 forKey:UncaughtExceptionHandlerAddressesKey];
    
    NSException *exception = [NSException
     exceptionWithName: UncaughtExceptionHandlerSignalExceptionName reason: [NSString stringWithFormat:
      NSLocalizedString(@"Signal %d was raised.", nil),
      signal] userInfo: userInfo];
    return [NSString stringWithFormat:@"%@, %@, %@", exception.name, exception.reason, exception.userInfo];
}

+ (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;
}

@end

 

posted @ 2017-07-28 15:19  MJHelloWorld  阅读(1857)  评论(0编辑  收藏  举报