在应用程序iOS崩溃后显示alertview

在应用程序iOS崩溃后显示alertview,ios,objective-c,exception,uialertview,Ios,Objective C,Exception,Uialertview,我正在尝试向用户显示alertview after crash应用程序,以提供有关崩溃的一些信息。例如,;“您发生故障,我们将尽快修复。”是否可以在此处显示alertview 我从这里得到了这部分代码,并将alertview放入其中 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSSetUncaughtEx

我正在尝试向用户显示alertview after crash应用程序,以提供有关崩溃的一些信息。例如,;“您发生故障,我们将尽快修复。”是否可以在此处显示alertview

我从这里得到了这部分代码,并将alertview放入其中

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

      NSSetUncaughtExceptionHandler(&myExceptionHandler);

}

void myExceptionHandler(NSException *exception)
{

     UIAlertView *alert = [[UIAlertView alloc]
                      initWithTitle:@""
                      message:@"You got crash, we will fix as soon as possible!"
                      delegate:nil
                      cancelButtonTitle:@"Okay"
                      otherButtonTitles:nil, nil];
     [alert show];

     NSArray *stack = [exception callStackReturnAddresses];
     NSLog(@"Stack trace: %@", stack);

}
我还尝试了此代码来显示警报

[alert performSelectorOnMainThread:@selector(show) withObject:nil waitUntilDone:YES];

你不应该那样做

原因如下:

  • 当应用程序崩溃时,应用程序处于非常不稳定的状态。您可以尝试访问应用程序无法访问的内存,假设某个对象是特定类型的,而它不是,等等。如果您继续执行代码,您可能会覆盖/删除/损坏您的应用程序用户数据,因为您无法确定您的代码是否确实执行了您希望它执行的操作
  • 由于这种不稳定的状态,您不应该在崩溃时调用任何(!!)非异步安全代码,其中包括任何Objective-C代码。只允许使用C的一个子集,此时不应分配任何内存
  • 您的代码只会为未处理的异常触发警报(如果由于上述原因,它在大多数情况下都能工作)。但这些只是你的应用程序可能崩溃的一部分原因

  • 你可以改为询问用户下次启动应用程序时,在崩溃发生之前他做了什么。要检测应用程序是否崩溃,您可以使用多个第三方服务或(开源)库来检测崩溃,并(安全地)在崩溃时收集堆栈跟踪

    你不应该那样做

    原因如下:

  • 当应用程序崩溃时,应用程序处于非常不稳定的状态。您可以尝试访问应用程序无法访问的内存,假设某个对象是特定类型的,而它不是,等等。如果您继续执行代码,您可能会覆盖/删除/损坏您的应用程序用户数据,因为您无法确定您的代码是否确实执行了您希望它执行的操作
  • 由于这种不稳定的状态,您不应该在崩溃时调用任何(!!)非异步安全代码,其中包括任何Objective-C代码。只允许使用C的一个子集,此时不应分配任何内存
  • 您的代码只会为未处理的异常触发警报(如果由于上述原因,它在大多数情况下都能工作)。但这些只是你的应用程序可能崩溃的一部分原因

  • 你可以改为询问用户下次启动应用程序时,在崩溃发生之前他做了什么。要检测应用程序是否崩溃,您可以使用多个第三方服务或(开源)库来检测崩溃,并(安全地)在崩溃时收集堆栈跟踪

    发生碰撞时,我需要显示警告警报。我这样做了,它的工作

    请注意,只有在真正必要的情况下才应该使用这样的代码(就像我的情况一样,因为这不是@Kerni所说的好做法。我使用它来收集异常详细信息并将它们发送回我的web服务器,然后分析它们以修复问题)

    在我的AppDelegate.m中

    #import "UncaughtExceptionHandler.h"
    //[...]
    
    - (void)installUncaughtExceptionHandler
    {
        InstallUncaughtExceptionHandler();
    }
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        //[...]
    
        NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
    
        //[...]
    
    }
    
    //
    //  UncaughtExceptionHandler.m
    //  UncaughtExceptions
    //
    //  Created by Matt Gallagher on 2010/05/25.
    //  Copyright 2010 Matt Gallagher. All rights reserved.
    //
    //  Permission is given to use this source code file, free of charge, in any
    //  project, commercial or otherwise, entirely at your risk, with the condition
    //  that any redistribution (in part or whole) of source code must retain
    //  this copyright and permission notice. Attribution in compiled projects is
    //  appreciated but not required.
    //
    
    #import "UncaughtExceptionHandler.h"
    #include <libkern/OSAtomic.h>
    #include <execinfo.h>
    
    NSString * const UncaughtExceptionHandlerSignalExceptionName = @"UncaughtExceptionHandlerSignalExceptionName";
    NSString * const UncaughtExceptionHandlerSignalKey = @"UncaughtExceptionHandlerSignalKey";
    NSString * const UncaughtExceptionHandlerAddressesKey = @"UncaughtExceptionHandlerAddressesKey";
    
    volatile int32_t UncaughtExceptionCount = 0;
    const int32_t UncaughtExceptionMaximum = 10;
    
    const NSInteger UncaughtExceptionHandlerSkipAddressCount = 4;
    const NSInteger UncaughtExceptionHandlerReportAddressCount = 5;
    
    @implementation UncaughtExceptionHandler
    
    + (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;
    }
    
    - (void)handleException:(NSException *)exception
    {
        //here you can show your alert
         UIAlertView *alert = [[UIAlertView alloc]
                          initWithTitle:@""
                          message:@"You got crash, we will fix as soon as possible!"
                          delegate:nil
                          cancelButtonTitle:@"Okay"
                          otherButtonTitles:nil, nil];
         [alert show];
    
        NSString* reason = [exception reason];
        if([reason length]>200)
        {
            reason = [[reason substringToIndex:200] stringByAppendingString:@" [...]"];
        }
    
        CFRunLoopRef runLoop = CFRunLoopGetCurrent();
        CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);
    
        for (NSString *mode in (__bridge NSArray *)allModes)
        {
            CFRunLoopRunInMode((CFStringRef)mode, 0.001, false);
        }
    
        CFRelease(allModes);
    
        NSSetUncaughtExceptionHandler(NULL);
        signal(SIGABRT, SIG_DFL);
        signal(SIGILL, SIG_DFL);
        signal(SIGSEGV, SIG_DFL);
        signal(SIGFPE, SIG_DFL);
        signal(SIGBUS, SIG_DFL);
        signal(SIGPIPE, SIG_DFL);
    
        if ([[exception name] isEqual:UncaughtExceptionHandlerSignalExceptionName])
        {
            kill(getpid(), [[[exception userInfo] objectForKey:UncaughtExceptionHandlerSignalKey] intValue]);
        }
        else
        {
            [exception raise];
        }
    }
    
    @end
    
    void HandleException(NSException *exception)
    {
        int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);
        if (exceptionCount > UncaughtExceptionMaximum)
        {
            return;
        }
    
        NSArray *callStack = [exception callStackSymbols];
        NSMutableDictionary *userInfo =
        [NSMutableDictionary dictionaryWithDictionary:[exception userInfo]];
        [userInfo
         setObject:callStack
         forKey:UncaughtExceptionHandlerAddressesKey];
    
        [[[UncaughtExceptionHandler alloc] init]
         performSelectorOnMainThread:@selector(handleException:)
         withObject:
         [NSException
          exceptionWithName:[exception name]
          reason:[exception reason]
          userInfo:userInfo]
         waitUntilDone:YES];
    }
    
    void SignalHandler(int signal)
    {
        int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);
        if (exceptionCount > UncaughtExceptionMaximum)
        {
            return;
        }
    
        NSMutableDictionary *userInfo =
        [NSMutableDictionary
         dictionaryWithObject:[NSNumber numberWithInt:signal]
         forKey:UncaughtExceptionHandlerSignalKey];
    
        NSArray *callStack = [UncaughtExceptionHandler backtrace];
        [userInfo
         setObject:callStack
         forKey:UncaughtExceptionHandlerAddressesKey];
    
        [[[UncaughtExceptionHandler alloc] init]
         performSelectorOnMainThread:@selector(handleException:)
         withObject:
         [NSException
          exceptionWithName:UncaughtExceptionHandlerSignalExceptionName
          reason:
          [NSString stringWithFormat:
           NSLocalizedString(@"Signal %d was raised.", nil),
           signal]
          userInfo:
          [NSDictionary
           dictionaryWithObject:[NSNumber numberWithInt:signal]
           forKey:UncaughtExceptionHandlerSignalKey]]
         waitUntilDone:YES];
    }
    
    void InstallUncaughtExceptionHandler()
    {
        NSSetUncaughtExceptionHandler(&HandleException);
        signal(SIGABRT, SignalHandler);
        signal(SIGILL, SignalHandler);
        signal(SIGSEGV, SignalHandler);
        signal(SIGFPE, SignalHandler);
        signal(SIGBUS, SignalHandler);
        signal(SIGPIPE, SignalHandler);
    }
    
    我的UncaughtExceptionHandler.h

    //
    //  UncaughtExceptionHandler.h
    //  UncaughtExceptions
    //
    //  Created by Matt Gallagher on 2010/05/25.
    //  Copyright 2010 Matt Gallagher. All rights reserved.
    //
    //  Permission is given to use this source code file, free of charge, in any
    //  project, commercial or otherwise, entirely at your risk, with the condition
    //  that any redistribution (in part or whole) of source code must retain
    //  this copyright and permission notice. Attribution in compiled projects is
    //  appreciated but not required.
    //
    
    #import <UIKit/UIKit.h>
    
    @interface UncaughtExceptionHandler : NSObject<UIAlertViewDelegate>
    {
        NSException* currentException;
    }
    
    @end
    
    void InstallUncaughtExceptionHandler();
    
    //
    //UncaughtExceptionHandler.h
    //未捕获的异常
    //
    //由马特·加拉赫于2010年5月25日创作。
    //版权所有2010马特·加拉赫。保留所有权利。
    //
    //允许以任何形式免费使用此源代码文件
    //项目,商业或其他,完全由您承担风险,条件
    //源代码的任何重新分发(部分或全部)都必须保留
    //此版权和许可声明。编译项目的归属为
    //感激但不是必需的。
    //
    #进口
    @接口UncaughtExceptionHandler:NSObject
    {
    NSException*currentException;
    }
    @结束
    void InstallUncaughtExceptionHandler();
    
    我的UncaughtExceptionHandler.m

    #import "UncaughtExceptionHandler.h"
    //[...]
    
    - (void)installUncaughtExceptionHandler
    {
        InstallUncaughtExceptionHandler();
    }
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        //[...]
    
        NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
    
        //[...]
    
    }
    
    //
    //  UncaughtExceptionHandler.m
    //  UncaughtExceptions
    //
    //  Created by Matt Gallagher on 2010/05/25.
    //  Copyright 2010 Matt Gallagher. All rights reserved.
    //
    //  Permission is given to use this source code file, free of charge, in any
    //  project, commercial or otherwise, entirely at your risk, with the condition
    //  that any redistribution (in part or whole) of source code must retain
    //  this copyright and permission notice. Attribution in compiled projects is
    //  appreciated but not required.
    //
    
    #import "UncaughtExceptionHandler.h"
    #include <libkern/OSAtomic.h>
    #include <execinfo.h>
    
    NSString * const UncaughtExceptionHandlerSignalExceptionName = @"UncaughtExceptionHandlerSignalExceptionName";
    NSString * const UncaughtExceptionHandlerSignalKey = @"UncaughtExceptionHandlerSignalKey";
    NSString * const UncaughtExceptionHandlerAddressesKey = @"UncaughtExceptionHandlerAddressesKey";
    
    volatile int32_t UncaughtExceptionCount = 0;
    const int32_t UncaughtExceptionMaximum = 10;
    
    const NSInteger UncaughtExceptionHandlerSkipAddressCount = 4;
    const NSInteger UncaughtExceptionHandlerReportAddressCount = 5;
    
    @implementation UncaughtExceptionHandler
    
    + (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;
    }
    
    - (void)handleException:(NSException *)exception
    {
        //here you can show your alert
         UIAlertView *alert = [[UIAlertView alloc]
                          initWithTitle:@""
                          message:@"You got crash, we will fix as soon as possible!"
                          delegate:nil
                          cancelButtonTitle:@"Okay"
                          otherButtonTitles:nil, nil];
         [alert show];
    
        NSString* reason = [exception reason];
        if([reason length]>200)
        {
            reason = [[reason substringToIndex:200] stringByAppendingString:@" [...]"];
        }
    
        CFRunLoopRef runLoop = CFRunLoopGetCurrent();
        CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);
    
        for (NSString *mode in (__bridge NSArray *)allModes)
        {
            CFRunLoopRunInMode((CFStringRef)mode, 0.001, false);
        }
    
        CFRelease(allModes);
    
        NSSetUncaughtExceptionHandler(NULL);
        signal(SIGABRT, SIG_DFL);
        signal(SIGILL, SIG_DFL);
        signal(SIGSEGV, SIG_DFL);
        signal(SIGFPE, SIG_DFL);
        signal(SIGBUS, SIG_DFL);
        signal(SIGPIPE, SIG_DFL);
    
        if ([[exception name] isEqual:UncaughtExceptionHandlerSignalExceptionName])
        {
            kill(getpid(), [[[exception userInfo] objectForKey:UncaughtExceptionHandlerSignalKey] intValue]);
        }
        else
        {
            [exception raise];
        }
    }
    
    @end
    
    void HandleException(NSException *exception)
    {
        int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);
        if (exceptionCount > UncaughtExceptionMaximum)
        {
            return;
        }
    
        NSArray *callStack = [exception callStackSymbols];
        NSMutableDictionary *userInfo =
        [NSMutableDictionary dictionaryWithDictionary:[exception userInfo]];
        [userInfo
         setObject:callStack
         forKey:UncaughtExceptionHandlerAddressesKey];
    
        [[[UncaughtExceptionHandler alloc] init]
         performSelectorOnMainThread:@selector(handleException:)
         withObject:
         [NSException
          exceptionWithName:[exception name]
          reason:[exception reason]
          userInfo:userInfo]
         waitUntilDone:YES];
    }
    
    void SignalHandler(int signal)
    {
        int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);
        if (exceptionCount > UncaughtExceptionMaximum)
        {
            return;
        }
    
        NSMutableDictionary *userInfo =
        [NSMutableDictionary
         dictionaryWithObject:[NSNumber numberWithInt:signal]
         forKey:UncaughtExceptionHandlerSignalKey];
    
        NSArray *callStack = [UncaughtExceptionHandler backtrace];
        [userInfo
         setObject:callStack
         forKey:UncaughtExceptionHandlerAddressesKey];
    
        [[[UncaughtExceptionHandler alloc] init]
         performSelectorOnMainThread:@selector(handleException:)
         withObject:
         [NSException
          exceptionWithName:UncaughtExceptionHandlerSignalExceptionName
          reason:
          [NSString stringWithFormat:
           NSLocalizedString(@"Signal %d was raised.", nil),
           signal]
          userInfo:
          [NSDictionary
           dictionaryWithObject:[NSNumber numberWithInt:signal]
           forKey:UncaughtExceptionHandlerSignalKey]]
         waitUntilDone:YES];
    }
    
    void InstallUncaughtExceptionHandler()
    {
        NSSetUncaughtExceptionHandler(&HandleException);
        signal(SIGABRT, SignalHandler);
        signal(SIGILL, SignalHandler);
        signal(SIGSEGV, SignalHandler);
        signal(SIGFPE, SignalHandler);
        signal(SIGBUS, SignalHandler);
        signal(SIGPIPE, SignalHandler);
    }
    
    //
    //UncaughtExceptionHandler.m
    //未捕获的异常
    //
    //由马特·加拉赫于2010年5月25日创作。
    //版权所有2010马特·加拉赫。保留所有权利。
    //
    //允许以任何形式免费使用此源代码文件
    //项目,商业或其他,完全由您承担风险,条件
    //源代码的任何重新分发(部分或全部)都必须保留
    //此版权和许可声明。编译项目的归属为
    //感激但不是必需的。
    //
    #导入“UncaughtExceptionHandler.h”
    #包括
    #包括
    NSString*常量UncaughtExceptionHandlerSignalExceptionName=@“UncaughtExceptionHandlerSignalExceptionName”;
    NSString*常量UncaughtExceptionHandlerSignalKey=@“UncaughtExceptionHandlerSignalKey”;
    NSString*常量UncaughtExceptionHandlerAddressSkey=@“UncaughtExceptionHandlerAddressSkey”;
    volatile int32_t UncaughtExceptionCount=0;
    常量int32_t UncaughtExceptionMaximum=10;
    const NSInteger uncaughtexception handlerskipaddresscount=4;
    const NSInteger UncaughtExceptionHandlerReportAddressCount=5;
    @实现UncaughtExceptionHandler
    +(NSArray*)回溯
    {
    void*callstack[128];
    int frames=backtrace(调用堆栈,128);
    char**strs=回溯_符号(调用堆栈、帧);
    int i;
    NSMutableArray*回溯=[NSMutableArray阵列容量:帧];
    为了(
    i=未捕获的例外HandlerSkipAddressCount;
    i200)
    {
    原因=[[reason sub]