亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > iOS > 正文

iOS中程序異常Crash友好化處理詳解

2019-10-21 18:40:05
字體:
來源:轉載
供稿:網友

前言

前兩天接到個面試,面試官問到上線的app怎么避免閃退,首先想到的就是在編碼的時候進行各種容錯,但貌似并不是面試官想要的答案,所以表現的很糟糕。今天有時間就來整理一下,希望有所幫助。

實現效果如圖:

iOS,程序異常,Crash,友好化

效果實現:

iOS,程序異常,Crash,友好化

用法:

1.將截圖的中CatchedHelper文件夾拖到你的項目工程中。

2.在AppDelegate.m中找到以下方法并如下添加代碼:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch.  [UncaughtExceptionHandler installUncaughtExceptionHandler:YES showAlert:YES]; return YES;}

以上代碼就可以實現稍微友好一點的crash攔截處理。

代碼解釋:

UncaughtExceptionHandler.h主要代碼:

#import <Foundation/Foundation.h>#import <UIKit/UIKit.h>@interface UncaughtExceptionHandler : NSObject/*! * 異常的處理方法 * * @param install 是否開啟捕獲異常 * @param showAlert 是否在發生異常時彈出alertView */+ (void)installUncaughtExceptionHandler:(BOOL)install showAlert:(BOOL)showAlert;@end

UncaughtExceptionHandler.m文件主要的代碼如下:

1.發送異常信號

/* * 異常的處理方法 * * @param install  是否開啟捕獲異常 * @param showAlert 是否在發生異常時彈出alertView */+ (void)installUncaughtExceptionHandler:(BOOL)install showAlert:(BOOL)showAlert {    if (install && showAlert) {    [[self alloc] alertView:showAlert];  }    NSSetUncaughtExceptionHandler(install ? HandleException : NULL);  signal(SIGABRT, install ? SignalHandler : SIG_DFL);  signal(SIGILL, install ? SignalHandler : SIG_DFL);  signal(SIGSEGV, install ? SignalHandler : SIG_DFL);  signal(SIGFPE, install ? SignalHandler : SIG_DFL);  signal(SIGBUS, install ? SignalHandler : SIG_DFL);  signal(SIGPIPE, install ? SignalHandler : SIG_DFL);}

產生上述的signal的時候就會調用我們定義的SignalHandler來處理異常。

ps: NSSetUncaughtExceptionHandler就是iOS SDK中提供的一個現成的函數,用來捕獲異常的方法,使用方便。但它不能捕獲拋出的signal,所以定義了SignalHandler方法。

2.處理異常

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];    //在主線程中,執行制定的方法, withObject是執行方法傳入的參數  [[[UncaughtExceptionHandler alloc] init]   performSelectorOnMainThread:@selector(handleException:)   withObject:   [NSException exceptionWithName:[exception name]               reason:[exception reason]              userInfo:userInfo]   waitUntilDone:YES];}

該方法就是對應NSSetUncaughtExceptionHandler的處理,只要方法關聯到這個函數,那么發生相應錯誤時會自動調用該函數,調用時會傳入exception參數。獲取異常后會將捕獲的異常傳入最終調用處理的handleException函數。

3.無法捕獲的signal處理

//處理signal報錯void SignalHandler(int signal) {    int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);  // 如果太多不用處理  if (exceptionCount > UncaughtExceptionMaximum) {    return;  }    NSString* description = nil;  switch (signal) {    case SIGABRT:      description = [NSString stringWithFormat:@"Signal SIGABRT was raised!/n"];      break;    case SIGILL:      description = [NSString stringWithFormat:@"Signal SIGILL was raised!/n"];      break;    case SIGSEGV:      description = [NSString stringWithFormat:@"Signal SIGSEGV was raised!/n"];      break;    case SIGFPE:      description = [NSString stringWithFormat:@"Signal SIGFPE was raised!/n"];      break;    case SIGBUS:      description = [NSString stringWithFormat:@"Signal SIGBUS was raised!/n"];      break;    case SIGPIPE:      description = [NSString stringWithFormat:@"Signal SIGPIPE was raised!/n"];      break;    default:      description = [NSString stringWithFormat:@"Signal %d was raised!",signal];  }    NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];  NSArray *callStack = [UncaughtExceptionHandler backtrace];  [userInfo setObject:callStack forKey:UncaughtExceptionHandlerAddressesKey];  [userInfo setObject:[NSNumber numberWithInt:signal] forKey:UncaughtExceptionHandlerSignalKey];    //在主線程中,執行指定的方法, withObject是執行方法傳入的參數  [[[UncaughtExceptionHandler alloc] init]   performSelectorOnMainThread:@selector(handleException:)   withObject:   [NSException exceptionWithName:UncaughtExceptionHandlerSignalExceptionName               reason: description              userInfo: userInfo]   waitUntilDone:YES];}

以上方法是對于捕獲不到的signal信號進行處理,列出常見的異常類型。

4.堆棧調用

//獲取調用堆棧+ (NSArray *)backtrace {    //指針列表  void* callstack[128];  //backtrace用來獲取當前線程的調用堆棧,獲取的信息存放在這里的callstack中  //128用來指定當前的buffer中可以保存多少個void*元素  //返回值是實際獲取的指針個數  int frames = backtrace(callstack, 128);  //backtrace_symbols將從backtrace函數獲取的信息轉化為一個字符串數組  //返回一個指向字符串數組的指針  //每個字符串包含了一個相對于callstack中對應元素的可打印信息,包括函數名、偏移地址、實際返回地址  char **strs = backtrace_symbols(callstack, frames);    int i;  NSMutableArray *backtrace = [NSMutableArray arrayWithCapacity:frames];  for (i = 0; i < frames; i++) {        [backtrace addObject:[NSString stringWithUTF8String:strs[i]]];  }  free(strs);    return backtrace;}

backtrace是Linux下用來追蹤函數調用堆棧以及定位段錯誤的函數。

5.使用UIAlerView進行友好化提示

- (void)handleException:(NSException *)exception {    [self validateAndSaveCriticalApplicationData:exception];    if (!showAlertView) {    return;  }  #pragma clang diagnostic push#pragma clang diagnostic ignored "-Wdeprecated-declarations"  UIAlertView *alert =  [[UIAlertView alloc]   initWithTitle:@"出錯啦"   message:[NSString stringWithFormat:@"你可以嘗試繼續操作,但是應用可能無法正常運行./n"]   delegate:self   cancelButtonTitle:@"退出"   otherButtonTitles:@"繼續", nil];  [alert show];#pragma clang diagnostic pop    CFRunLoopRef runLoop = CFRunLoopGetCurrent();  CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);    while (!self.dismissed) {    //點擊繼續    for (NSString *mode in (__bridge NSArray *)allModes) {      //快速切換Mode      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];  }}

在這里你可以做自己的crash收集操作,例如上傳服務器等。

源碼下載

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網的支持。


注:相關教程知識閱讀請移步到IOS開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩在线视频线视频免费网站| 亚洲夜晚福利在线观看| 欧美日韩在线视频一区| 国产乱人伦真实精品视频| 国产精品黄色影片导航在线观看| 中文字幕av一区二区三区谷原希美| 欧美性猛交xxxx富婆| 久久久久成人精品| 国产欧美日韩专区发布| 亚洲人成欧美中文字幕| 啪一啪鲁一鲁2019在线视频| 国外色69视频在线观看| 亚洲激情第一页| 一区二区三区久久精品| 久久99青青精品免费观看| 欧美亚洲另类视频| 国产丝袜精品第一页| 欧美在线视频a| 日韩在线观看免费网站| 国产欧美日韩综合精品| 精品亚洲一区二区三区在线观看| 欧美性受xxxx白人性爽| 亚洲午夜精品久久久久久久久久久久| 最近2019中文字幕第三页视频| 91久久在线观看| 91在线观看免费高清| 国产日韩精品在线| 亚洲三级 欧美三级| 日韩国产一区三区| 国产精品18久久久久久麻辣| 久久人人看视频| 色综合久久天天综线观看| 国产成人亚洲精品| 国产69久久精品成人看| 中文字幕亚洲无线码在线一区| 午夜剧场成人观在线视频免费观看| 久久伊人精品视频| 久久五月天综合| 日韩成人中文字幕在线观看| 国产一区二区三区中文| 日韩男女性生活视频| 精品亚洲一区二区三区四区五区| 亚洲精品白浆高清久久久久久| 日本成熟性欧美| 亚洲午夜性刺激影院| 国产精品久久久久久中文字| 91po在线观看91精品国产性色| 欧美在线视频观看免费网站| 亚洲一二在线观看| 午夜精品一区二区三区av| 国产精品视频专区| 亚洲国产精品小视频| 一区二区三区视频免费| 疯狂做受xxxx欧美肥白少妇| 欧美区二区三区| 国产精品成人va在线观看| 欧洲成人免费aa| 在线日韩精品视频| 成人精品在线视频| 国产精品69久久| 国产精品久久久久久av下载红粉| 国产精品美女久久久久av超清| 精品视频中文字幕| 国产成人午夜视频网址| 精品国产一区二区三区久久久| 精品福利在线观看| 精品视频久久久久久| 中文字幕在线亚洲| 成人美女av在线直播| 91sa在线看| 欧美又大粗又爽又黄大片视频| 欧美激情va永久在线播放| 国产欧美久久一区二区| 国内精品国产三级国产在线专| 色综合91久久精品中文字幕| 亚洲直播在线一区| 91在线|亚洲| 久久中文精品视频| 欧美综合国产精品久久丁香| 亚洲美女黄色片| 欧美日韩精品在线播放| 亚洲精品黄网在线观看| 57pao国产成人免费| 欧美一级免费看| 欧美多人乱p欧美4p久久| 美女国内精品自产拍在线播放| 久久亚洲影音av资源网| 一本大道久久加勒比香蕉| 亚洲**2019国产| 亚洲国产高清高潮精品美女| 日韩欧美亚洲一二三区| 欧美日韩国产一区二区三区| 亚洲自拍偷拍色片视频| 欧美性猛交xxxx乱大交蜜桃| 欧美亚洲视频在线观看| 日韩欧美在线视频日韩欧美在线视频| 亚洲免费小视频| 久久亚洲精品中文字幕冲田杏梨| 一区二区欧美在线| 国产一区二区三区视频在线观看| 精品成人国产在线观看男人呻吟| www高清在线视频日韩欧美| 一区二区亚洲精品国产| 国产女人18毛片水18精品| 亚洲电影中文字幕| 亚洲女人天堂网| 欧美日韩在线免费观看| 国产欧美久久久久久| 欧洲成人午夜免费大片| 精品国产一区二区三区久久狼黑人| 久久久人成影片一区二区三区观看| 一区二区欧美激情| 日韩精品视频在线观看免费| 亚洲精品动漫100p| 91精品国产网站| 久久久亚洲网站| 日韩av一区二区在线观看| 亚洲护士老师的毛茸茸最新章节| 精品国产成人av| 最新国产成人av网站网址麻豆| 久久久久久欧美| 综合av色偷偷网| 日韩国产一区三区| 久久久久日韩精品久久久男男| 精品久久久久久久久久久久久| 成人深夜直播免费观看| 国产精品视频不卡| 青青久久aⅴ北条麻妃| 国产成人拍精品视频午夜网站| 热99精品只有里视频精品| 成人黄色大片在线免费观看| 精品人伦一区二区三区蜜桃免费| 国产精品一区二区三区久久久| 国产成人91久久精品| 亚洲国产精品久久久久久| 国产日本欧美一区二区三区在线| 最近日韩中文字幕中文| 欧美一乱一性一交一视频| 2019日本中文字幕| 成人午夜小视频| 8x海外华人永久免费日韩内陆视频| 91在线观看免费高清完整版在线观看| 日产日韩在线亚洲欧美| 久久五月天综合| 992tv成人免费视频| 午夜精品福利在线观看| 国产精品老女人精品视频| 欧美激情免费视频| 亚洲精品成人免费| 国产福利精品av综合导导航| 久久99亚洲热视| 欧美裸体男粗大视频在线观看| 国产成人精品一区二区| 国产日韩换脸av一区在线观看| 欧美激情久久久久久| 大伊人狠狠躁夜夜躁av一区| 欧美激情免费视频| 欧美中文字幕视频在线观看| 亚洲一区二区久久久久久久| 538国产精品一区二区在线| 欧美多人爱爱视频网站| 国内外成人免费激情在线视频| 久操成人在线视频| 欧美性猛交xxxx久久久|