標籤:
iOS開發中我們會遇到程式拋出異常退出的情況,如果是在調試的過程中,異常的資訊是一目瞭然,但是如果是在已經發布的程式中,擷取異常的資訊有時候是比較困難的。
iOS提供了異常發生的處理API,我們在程式啟動的時候可以添加這樣的Handler,這樣的程式發生異常的時候就可以對這一部分的資訊進行必要的處理,適時的反饋給開發人員。
首先定義一個類SignalHandler
@interface SignalHandler : NSObject
+ (instancetype)Instance;
- (void)setExceptionHandler;
@end
實現SignalHandler.m
#import "SignalHandler.h"
#import <UIKit/UIKit.h>
#include <libkern/OSAtomic.h>
#include <execinfo.h>
@interface SignalHandler ()
{
BOOL isDismissed ;
}
- (void)HandleException1:(NSException *)exception;
@end
//捕獲訊號後的回呼函數
void HandleException(NSException *exception)
{
//處理異常訊息
[[SignalHandler Instance] performSelectorOnMainThread:@selector(HandleException1:) withObject:exception waitUntilDone:YES];
}
@implementation SignalHandler
static SignalHandler *s_SignalHandler = nil;
+ (instancetype)Instance{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (s_SignalHandler == nil) {
s_SignalHandler = [[SignalHandler alloc] init];
}
});
return s_SignalHandler;
}
- (void)setExceptionHandler
{
NSSetUncaughtExceptionHandler(&HandleException);
}
//處理異常用到的方法
- (void)HandleException1:(NSException *)exception
{
CFRunLoopRef runLoop = CFRunLoopGetCurrent();
CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);
//異常的堆棧資訊
NSArray *stackArray = [exception callStackSymbols];
//出現異常的原因
NSString *reason = [exception reason];
// 異常名稱
NSString *name = [exception name];
NSString *exceptionInfo = [NSString stringWithFormat:@"原因:%@\n名稱:%@\n堆棧:%@",name, reason, stackArray];
NSLog(@"%@", exceptionInfo);
//此處也可以把exceptionInfo儲存檔案
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"程式出現問題啦" message:exceptionInfo delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:nil];
[alertView show];
//當接收到異常處理訊息時,讓程式開始runloop,防止程式死亡
while (!isDismissed) {
for (NSString *mode in (__bridge NSArray *)allModes)
{
CFRunLoopRunInMode((CFStringRef)mode, 0.001, false);
}
}
//當點擊彈出視圖的Cancel按鈕哦,isDimissed = YES,上邊的迴圈跳出
CFRelease(allModes);
NSSetUncaughtExceptionHandler(NULL);
}
- (void)alertView:(UIAlertView *)anAlertView clickedButtonAtIndex:(NSInteger)anIndex
{
//因為這個彈出視圖只有一個Cancel按鈕,所以直接進行修改isDimsmissed這個變數了
isDismissed = YES;
}
最後需要在
didFinishLaunchingWithOptions中添加
[[SignalHandler Instance] setExceptionHandler];
完成後就可以進行驗證了,加入以下代碼
NSArray *array = [NSArray arrayWithObjects:@"1", nil];
[array objectAtIndex:2];
IOS 捕獲程式異常