You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义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];

额外说明

  1. 仅捕获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中调用此方法即可补充捕获信号崩溃。

  1. 避免干扰客户端逻辑:必须保存并调用客户端原有的异常处理器,否则会覆盖客户端自身的崩溃捕获逻辑。

  2. 上报时机注意:崩溃后应用处于不稳定状态,建议先将崩溃日志写入本地文件,待下次启动SDK时再上报至服务器,避免上报过程中再次崩溃。

内容的提问来源于stack exchange,提问作者Yuvaraj.M

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 12:26:05