Reputation: 1914
I am trying to show the user alertview after crash app for give some information about crash. Such as; "You got crash, we will fix as soon as possible." Is it possible to show the alertview in here?
I got this part of code from here and i put alertview inside it.
- (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];
Upvotes: 1
Views: 1098
Reputation: 2435
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.
In my AppDelegate.m
#import "UncaughtExceptionHandler.h"
//[...]
- (void)installUncaughtExceptionHandler
{
InstallUncaughtExceptionHandler();
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//[...]
NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
//[...]
}
My 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
// 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);
}
Upvotes: 0
Reputation: 15339
You should not do that.
Here is why:
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.
Upvotes: 5