拒绝闪退!让iOS应用从容地崩溃

虽然大家都不愿意看到程序崩溃,但可能崩溃是每个应用必须面对的现实,既然崩溃已经发生,无法阻挡了,那我们就让它崩也崩得淡定点吧。

IOS SDK中提供了一个现成的函数 NSSetUncaughtExceptionHandler 用来做异常处理,但功能非常有限,而引起崩溃的大多数原因如:内存访问错误,重复释放等错误就无能为力了,因为这种错误它抛出的是Signal,所以必须要专门做Signal处理。在didFinishLaunchingWithOptions 中,加入

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
Source code    

signal ( SIGABRT, MySignalHandler );

signal ( SIGILL, MySignalHandler );

signal ( SIGSEGV, MySignalHandler );

signal ( SIGFPE, MySignalHandler );

signal (SIGBUS, MySignalHandler );

signal (SIGPIPE, MySignalHandler );

回调函数MySignalHandler的定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
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 ];

}

这段代码将会在崩溃时弹出一个对话框,我们还可以让它显示出设备信息,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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;

}

在程序中加入这些代码之后,基本上所有崩溃都能Hold住了。崩溃时将会显示出如下的对话框:

这样在崩溃时还能从容地弹出对话框,比起闪退来,用户也不会觉得那么不爽。然后在下次启动时还可以通过邮件来发送Crash文件到邮箱,这就看各个应用的需求了。

你可能感兴趣的:(iOS)