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