【问题标题】:Objective-C/iPhone - NSException capturing as much information as possibleObjective-C/iPhone - NSException 捕获尽可能多的信息
【发布时间】:2011-07-26 21:48:27
【问题描述】:

我正在使用以下代码在我的应用中捕获异常:

void uncaughtExceptionHandler(NSException *exception) {
    [FlurryAPI logError:@"Uncaught" message:@"Crash!" exception:exception];
}

只是想知道我是否可以指出错误发生的位置、行号、UIView、类等。理想情况下,我希望获得尽可能多的详细信息,因为它是由 FlurryAPIanalytics 捕获的。

FlurryAPI: http://www.flurry.com/

【问题讨论】:

    标签: iphone objective-c exception nsexception


    【解决方案1】:

    我最终选择了这个:

    void uncaughtExceptionHandler(NSException *exception) {
        NSArray *backtrace = [exception callStackSymbols];
        NSString *platform = [[UIDevice currentDevice] platform];
        NSString *version = [[UIDevice currentDevice] systemVersion];
        NSString *message = [NSString stringWithFormat:@"Device: %@. OS: %@. Backtrace:\n%@",
                             platform,
                             version,
                             backtrace];
    
        [FlurryAPI logError:@"Uncaught" message:message exception:exception];
    }
    

    更新(基于@TommyG 下面的评论):

    NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler); 添加到AppDelegate 中的--(BOOL)application:didFinishLaunchingWithOptions: 方法的末尾。然后将上述方法也添加到AppDelegate中。

    【讨论】:

    • 你把这个方法放在哪里?它在应用程序委托中吗?我收到一条警告,说此方法没有以前的原型..
    • @TommyG 将 NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler); 添加到 AppDelegate 中 - (BOOL)application:didFinishLaunchingWithOptions: 方法的末尾。然后将上述方法也添加到 AppDelegate 中。
    • 这真的会给你一个堆栈跟踪吗?
    【解决方案2】:

    您可以利用预编译器并编写一个收集所有值的宏,例如:

    #define __ThrowException(name, reason, class, function, file, line, info) [NSException exceptionWithName:name reason:[NSString stringWithFormat:@"%s:%i (%@:%s) %@", file, line, class, function, reason]  userInfo:info];
    #define ThrowException(name, reason, info) __ThrowException(name, reason, [self class], _cmd, __FILE__, __LINE__, info)
    

    但是,这仅在您从 ObjC 函数内部抛出异常时才有效(self 和 _cmd 是您在 ObjC 函数中获得的第一个参数,其中 self 是指向类的 id 和 @987654324 @ 到可以(当前!)类型转换为 const char 的选择器。

    但是,如果您只希望 Foundation 异常使用此功能,您有两种选择:

    1. 将所有可能引发异常的内容封装在 @try() @catch() 块中,然后引发新的自定义异常
    2. 获取堆栈跟踪,这可能有点困难,因为您的应用程序可能处于不一致的状态并且无法收集所有值。 here 详细介绍了收集当前堆栈跟踪。

    【讨论】:

    • 我明白了,我会在 AppDelegate 中定义这些宏吗?如果是这样,那么我将如何在我的 void uncaughtExceptionHandler(NSException *exception) 中使用它们?
    • @Fulvio Cusumano:嗯,宏不打算在您的处理程序中使用,因为此时从预编译器获取所需的值已经太晚了,但应该使用创建异常然后抛出它们。就像我说的,如果你只需要 Foundations 异常,你可以使用 @try() 和 @catch() 来创建一个新的异常或者走下堆栈。
    猜你喜欢
    • 2016-11-06
    • 2013-01-12
    • 2017-02-08
    • 2011-07-23
    • 2014-06-30
    • 2015-12-21
    • 2011-03-14
    • 2011-08-27
    • 1970-01-01
    相关资源
    最近更新 更多