简体   繁体   English

在iOS应用崩溃后显示AlertView

[英]Show alertview after crash app iOS

I am trying to show the user alertview after crash app for give some information about crash. 我试图在崩溃应用程序后向用户显示alertview,以提供有关崩溃的一些信息。 Such as; 如; "You got crash, we will fix as soon as possible." “您当机,我们将尽快修复。” Is it possible to show the alertview in here? 是否可以在此处显示alertview?

I got this part of code from here and i put alertview inside it. 我从这里得到了这部分代码,并在其中放入了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);

}

I also tried this code for show the alert. 我也尝试使用此代码来显示警报。

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

You should not do that. 你不应该那样做。

Here is why: 原因如下:

  1. When your app crashed, the app is in an very unstable state. 当您的应用崩溃时,该应用处于非常不稳定的状态。 You could have tried to access memory that is outside of your apps reach, assume some object is of a specific type and it is not, and more. 您可能曾尝试访问应用程序无法访问的内存,并假设某些对象属于特定类型,而实际上并非如此。 If you continue to execute code, you might overwrite/delete/damage your apps user data as you can't be sure your code actually does what you want it to do. 如果您继续执行代码,则可能会覆盖/删除/损坏应用程序用户数据,因为您无法确定代码是否确实执行了您希望执行的操作。
  2. Because of that unstable state, you should not call any (!!) non async-safe code at crash time, which includes any Objective-C code. 由于状态不稳定,因此您不应在崩溃时调用任何(!!)非异步安全代码,包括任何Objective-C代码。 Only a subset of C is allowed and you should not allocate any memory at that time. 只允许C的一个子集,此时您不应分配任何内存。
  3. Your code would only trigger an alert (if it would even work in most cases due to the above) for unhandled exceptions. 您的代码只会针对未处理的异常触发警报(如果由于上述原因在大多数情况下甚至仍然有效)。 But those are only a subset of reason that your app might crash. 但这只是您的应用可能崩溃的部分原因。

What you can do instead is asking the user what he did before the crash occurred when your app starts the next time. 相反,您可以问的是用户下次启动应用程序时在崩溃发生之前他做了什么。 To detect if your app crashed, you can use multiple 3rd party services or (open source) libraries to detect a crash and (safely) collect stacktraces at crash time. 要检测您的应用程序是否崩溃,您可以使用多个第三方服务或(开放源代码)库来检测崩溃,并在崩溃时(安全)收集堆栈跟踪。

I needed to show a warning alert when a crash happened. 发生崩溃时,我需要显示警告警报。 I did this and it works. 我做到了,而且有效。

Please, note that you should use such a code only if really necessary (as it was in my case, as it is not a good practice as said by @Kerni here . I used it to collect exception details and send them back to my web server and then analyze them to fix issues. 请注意,只有在真正必要时,才应使用这样的代码(就我而言,这不是@Kerni 在此处所说的好习惯。我用它来收集异常详细信息并将其发送回我的网站服务器,然后对其进行分析以解决问题。

In my AppDelegate.m 在我的AppDelegate.m中

#import "UncaughtExceptionHandler.h"
//[...]

- (void)installUncaughtExceptionHandler
{
    InstallUncaughtExceptionHandler();
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    //[...]

    NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);

    //[...]

}

My UncaughtExceptionHandler.h 我的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();

my UncaughtExceptionHandler.m 我的UncaughtExceptionHandler.m

//
//  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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM