我试图在崩溃应用程序之后显示用户alertview以提供有关崩溃的一些信息。如; “你崩溃了,我们会尽快解决。”是否可以在这里显示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];
答案 0 :(得分:5)
你应该不那样做。
原因如下:
您可以做的是询问用户在您的应用程序下次启动时发生崩溃之前他做了什么。要检测您的应用程序是否崩溃,您可以使用多个第三方服务或(开源)库来检测崩溃并在崩溃时(安全地)收集堆栈跟踪。
答案 1 :(得分:0)
发生崩溃时我需要显示警告提醒。我做到了这一点并且有效。
请注意,只有在真的有必要时才应该使用这样的代码(就像我的情况一样,因为这不是@Kerni here所说的好习惯。我用它来收集异常细节并将它们发送回我的网络服务器,然后分析它们以解决问题。
在我的AppDelegate.m
中#import "UncaughtExceptionHandler.h"
//[...]
- (void)installUncaughtExceptionHandler
{
InstallUncaughtExceptionHandler();
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//[...]
NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
//[...]
}
我的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.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);
}