自定义iOS Framework崩溃捕获失效,如何实现崩溃详情采集?
iOS SDK 全局崩溃捕获实现方案
问题根源
你当前的handleException方法仅能处理手动传入的异常对象,无法自动捕获SDK中抛出的未捕获NSException。当调用crashTheSDK触发数组越界时,系统会直接终止应用,不会走到你的处理方法。要实现SDK内崩溃的自动捕获,需要注册全局未捕获异常处理器。
解决方案
通过NSSetUncaughtExceptionHandler注册全局异常捕获器,同时保留客户端原有的异常处理器,避免冲突。以下是修改后的CCrashlytics实现:
import Foundation @objc public class CCrashlytics: NSObject { @objc static let shared = CCrashlytics() private var originalExceptionHandler: NSUncaughtExceptionHandler? @objc public override init() { super.init() } // 注册全局异常捕获器 @objc public func registerExceptionHandler() { // 保存客户端原有的异常处理器 originalExceptionHandler = NSGetUncaughtExceptionHandler() // 设置自定义异常处理器 NSSetUncaughtExceptionHandler { [weak self] exception in self?.handleUncaughtException(exception: exception) // 调用客户端原有的异常处理器,保证原有逻辑不受影响 self?.originalExceptionHandler?(exception) } } // 处理未捕获的异常 private func handleUncaughtException(exception: NSException) { // 收集崩溃信息 let stackTrace = exception.callStackSymbols.joined(separator: "\n") let exceptionName = exception.name.rawValue let exceptionReason = exception.reason ?? "No reason provided" // 这里替换为上报服务器的逻辑 print("\n=== SDK崩溃捕获 ===") print("Exception: \(exceptionName)") print("Reason: \(exceptionReason)") print("StackTrace:\n\(stackTrace)\n") } // 模拟SDK崩溃 @objc public func crashTheSDK() { let array = [1, 2, 3, 4] let _ = array[10] } // 手动处理异常(保留原有功能) @objc public func handleException(exception: NSException) { handleUncaughtException(exception: exception) } // 可选:注销处理器,恢复客户端原有逻辑 @objc public func unregisterExceptionHandler() { NSSetUncaughtExceptionHandler(originalExceptionHandler) } }
客户端集成方式
在客户端初始化SDK时,调用注册方法即可:
// 初始化SDK并注册崩溃捕获 CCrashlytics *crashlytics = [CCrashlytics sharedInstance]; [crashlytics registerExceptionHandler]; // 触发测试崩溃 [crashlytics crashTheSDK];
额外说明
- 仅捕获NSException类型崩溃:上述方案只能处理Objective-C/Swift层面的NSException崩溃(比如数组越界、未识别选择器),对于C/C++层面的信号量崩溃(比如野指针、内存访问错误),需要额外通过
signal函数注册信号处理器,示例如下:
private func registerSignalHandlers() { let signals = [SIGABRT, SIGILL, SIGSEGV, SIGFPE, SIGBUS, SIGTRAP] for signal in signals { signal(signal) { signal in // 收集信号崩溃信息并上报 print("捕获到信号崩溃:\(signal)") // 可选:调用系统默认处理逻辑终止应用 signal(signal, SIG_DFL) raise(signal) } } }
在registerExceptionHandler中调用此方法即可补充捕获信号崩溃。
避免干扰客户端逻辑:必须保存并调用客户端原有的异常处理器,否则会覆盖客户端自身的崩溃捕获逻辑。
上报时机注意:崩溃后应用处于不稳定状态,建议先将崩溃日志写入本地文件,待下次启动SDK时再上报至服务器,避免上报过程中再次崩溃。
内容的提问来源于stack exchange,提问作者Yuvaraj.M
相关产品推荐
相关产品推荐

