久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

如何讓IOS應(yīng)用從容地崩潰

 quasiceo 2012-12-24

如何讓IOS應(yīng)用從容地崩潰

雖然大家都不愿意看到程序崩潰,但可能崩潰是每個(gè)應(yīng)用必須面對(duì)的現(xiàn)實(shí),既然崩潰已經(jīng)發(fā)生,,無(wú)法阻擋了,,那我們就讓它崩也崩得淡定點(diǎn)吧。

文/donglin

注:鑒于多名網(wǎng)友對(duì)文中代碼提出的質(zhì)疑,,小編聯(lián)系了作者,,迅速給予更正并更新。感謝大家的監(jiān)督與支持,!

雖然大家都不愿意看到程序崩潰,,但可能崩潰是每個(gè)應(yīng)用必須面對(duì)的現(xiàn)實(shí),既然崩潰已經(jīng)發(fā)生,,無(wú)法阻擋了,,那我們就讓它崩也崩得淡定點(diǎn)吧。

IOS SDK中提供了一個(gè)現(xiàn)成的函數(shù) NSSetUncaughtExceptionHandler 用來(lái)做異常處理,,但功能非常有限,,而引起崩潰的大多數(shù)原因如:內(nèi)存訪問(wèn)錯(cuò)誤,重復(fù)釋放等錯(cuò)誤就無(wú)能為力了,,因?yàn)檫@種錯(cuò)誤它拋出的是Signal,,所以必須要專門(mén)做Signal處理。首先定義一個(gè)UncaughtExceptionHandler類,,.h頭文件的代碼如下:

#import <UIKit/UIKit.h>

@interface UncaughtExceptionHandler : NSObject

{

BOOL dismissed;

}

@end

void InstallUncaughtExceptionHandler();

 

然后在.mm文件實(shí)現(xiàn)InstallUncaughtExceptionHandler(),,如下:

void InstallUncaughtExceptionHandler()

{

signal(SIGABRT, MySignalHandler);

signal(SIGILL, MySignalHandler);

signal(SIGSEGV, MySignalHandler);

signal(SIGFPE, MySignalHandler);

signal(SIGBUS, MySignalHandler);

signal(SIGPIPE, MySignalHandler);

}

 

這樣,當(dāng)應(yīng)用發(fā)生錯(cuò)誤而產(chǎn)生上述Signal后,,就將會(huì)進(jìn)入我們自定義的回調(diào)函數(shù)MySignalHandler,。為了得到崩潰時(shí)的現(xiàn)場(chǎng)信息,還可以加入一些獲取CallTrace及設(shè)備信息的代碼,,.mm文件的完整代碼如下:

#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)alertView:(UIAlertView *)anAlertView clickedButtonAtIndex:(NSInteger)anIndex

{

if (anIndex == 0)

{

dismissed = YES;

}

}

- (void)handleException:(NSException *)exception

{

UIAlertView *alert =

[[[UIAlertView alloc]

initWithTitle:NSLocalizedString(@"Unhandled exception", nil)

message:[NSString stringWithFormat:NSLocalizedString(

@"You can try to continue but the application may be unstable.\n"

@"%@\n%@", nil),

[exception reason],

[[exception userInfo] objectForKey:UncaughtExceptionHandlerAddressesKey]]

delegate:self

cancelButtonTitle:NSLocalizedString(@"Quit", nil)

otherButtonTitles:NSLocalizedString(@"Continue", nil), nil]

autorelease];

[alert show];

CFRunLoopRef runLoop = CFRunLoopGetCurrent();

CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);

while (!dismissed)

{

for (NSString *mode in (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

NSString* getAppInfo()

{

    NSString *appInfo = [NSString stringWithFormat:@"App : %@ %@(%@)\nDevice : %@\nOS Version : %@ %@\nUDID : %@\n",

                          [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"],

                          [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"],

                          [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"],

                          [UIDevice currentDevice].model,

                          [UIDevice currentDevice].systemName,

                          [UIDevice currentDevice].systemVersion,

                          [UIDevice currentDevice].uniqueIdentifier];

    NSLog(@"Crash!!!! %@", appInfo);

    return appInfo;

}

void MySignalHandler(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] autorelease]

performSelectorOnMainThread:@selector(handleException:)

withObject:

[NSException

exceptionWithName:UncaughtExceptionHandlerSignalExceptionName

reason:

[NSString stringWithFormat:

NSLocalizedString(@"Signal %d was raised.\n"

                                          @"%@", nil),

signal, getAppInfo()]

userInfo:

[NSDictionary

dictionaryWithObject:[NSNumber numberWithInt:signal]

forKey:UncaughtExceptionHandlerSignalKey]]

waitUntilDone:YES];

}

void InstallUncaughtExceptionHandler()

{

signal(SIGABRT, MySignalHandler);

signal(SIGILL, MySignalHandler);

signal(SIGSEGV, MySignalHandler);

signal(SIGFPE, MySignalHandler);

signal(SIGBUS, MySignalHandler);

signal(SIGPIPE, MySignalHandler);

}

 

在應(yīng)用自身的 didFinishLaunchingWithOptions 前,,加入一個(gè)函數(shù):

- (void)installUncaughtExceptionHandler

{

InstallUncaughtExceptionHandler();

}

 

最后,在 didFinishLaunchingWithOptions 中加入這一句代碼就行了:

[self InstallUncaughtExceptionHandler];

現(xiàn)在,,基本上所有崩潰都能Hold住了。崩潰時(shí)將會(huì)顯示出如下的對(duì)話框:

 

這樣在崩潰時(shí)還能從容地彈出對(duì)話框,,比起閃退來(lái),,用戶也不會(huì)覺(jué)得那么不爽。然后在下次啟動(dòng)時(shí)還可以通過(guò)郵件來(lái)發(fā)送Crash文件到郵箱,,這就看各個(gè)應(yīng)用的需求了,。

 

原文來(lái)自:觸控科技博客

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多