成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

如何讓iOS應用從容地崩潰

移動開發 iOS
我知道程序崩潰是大家都不愿意見到的問題,但是既然崩潰已經發生,無法阻擋了,那我們就讓它崩也崩得淡定點吧。

雖然大家都不愿意看到程序崩潰,但可能崩潰是每個應用必須面對的現實,既然崩潰已經發生,無法阻擋了,那我們就讓它崩也崩得淡定點吧。

iOS SDK中提供了一個現成的函數 NSSetUncaughtExceptionHandler 用來做異常處理,但功能非常有限,而引起崩潰的大多數原因如:內存訪問錯誤,重復釋放等錯誤就無能為力了,因為這種錯誤它拋出的是Signal,所以必須 要專門做Signal處理。首先定義一個UncaughtExceptionHandler類,.h頭文件的代碼如下:

  1. #import <UIKit/UIKit.h> 
  2. @interface UncaughtExceptionHandler : NSObject 
  3. BOOL dismissed; 
  4. @end 
  5. void InstallUncaughtExceptionHandler(); 
  6. 然后在.mm文件實現InstallUncaughtExceptionHandler(),如下: 
  7. void InstallUncaughtExceptionHandler() 
  8. signal(SIGABRT, MySignalHandler); 
  9. signal(SIGILL, MySignalHandler); 
  10. signal(SIGSEGV, MySignalHandler); 
  11. signal(SIGFPE, MySignalHandler); 
  12. signal(SIGBUS, MySignalHandler); 
  13. signal(SIGPIPE, MySignalHandler); 

這樣,當應用發生錯誤而產生上述Signal后,就將會進入我們自定義的回調函數MySignalHandler。為了得到崩潰時的現場信息,還可以加入一些獲取CallTrace及設備信息的代碼,.mm文件的完整代碼如下:

  1. #import "UncaughtExceptionHandler.h" 
  2. #include <libkern/OSAtomic.h> 
  3. #include <execinfo.h> 
  4. NSString * const UncaughtExceptionHandlerSignalExceptionName = @"UncaughtExceptionHandlerSignalExceptionName"
  5. NSString * const UncaughtExceptionHandlerSignalKey = @"UncaughtExceptionHandlerSignalKey"
  6. NSString * const UncaughtExceptionHandlerAddressesKey = @"UncaughtExceptionHandlerAddressesKey"
  7. volatile int32_t UncaughtExceptionCount = 0; 
  8. const int32_t UncaughtExceptionMaximum = 10; 
  9. const NSInteger UncaughtExceptionHandlerSkipAddressCount = 4; 
  10. const NSInteger UncaughtExceptionHandlerReportAddressCount = 5; 
  11. @implementation UncaughtExceptionHandler 
  12. + (NSArray *)backtrace 
  13.         void* callstack[128]; 
  14. int frames = backtrace(callstack, 128); 
  15. char **strs = backtrace_symbols(callstack, frames);   
  16. int i; 
  17. NSMutableArray *backtrace = [NSMutableArray arrayWithCapacity:frames]; 
  18. for ( 
  19. i = UncaughtExceptionHandlerSkipAddressCount; 
  20. i < UncaughtExceptionHandlerSkipAddressCount + 
  21. UncaughtExceptionHandlerReportAddressCount; 
  22. i++) 
  23. [backtrace addObject:[NSString stringWithUTF8String:strs[i]]]; 
  24. free(strs);   
  25. return backtrace; 
  26. - (void)alertView:(UIAlertView *)anAlertView clickedButtonAtIndex:(NSInteger)anIndex 
  27. if (anIndex == 0) 
  28. dismissed = YES; 
  29. - (void)handleException:(NSException *)exception 
  30. UIAlertView *alert = 
  31. [[[UIAlertView alloc] 
  32. initWithTitle:NSLocalizedString(@"Unhandled exception", nil) 
  33. message:[NSString stringWithFormat:NSLocalizedString( 
  34. @"You can try to continue but the application may be unstable.\n" 
  35. @"%@\n%@", nil), 
  36. [exception reason], 
  37. [[exception userInfo] objectForKey:UncaughtExceptionHandlerAddressesKey]] 
  38. delegate:self 
  39. cancelButtonTitle:NSLocalizedString(@"Quit", nil) 
  40. otherButtonTitles:NSLocalizedString(@"Continue", nil), nil] 
  41. autorelease]; 
  42. [alert show];    
  43. CFRunLoopRef runLoop = CFRunLoopGetCurrent(); 
  44. CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);    
  45. while (!dismissed) 
  46. for (NSString *mode in (NSArray *)allModes) 
  47. CFRunLoopRunInMode((CFStringRef)mode, 0.001, false); 
  48. }    
  49. CFRelease(allModes); 
  50. NSSetUncaughtExceptionHandler(NULL); 
  51. signal(SIGABRT, SIG_DFL); 
  52. signal(SIGILL, SIG_DFL); 
  53. signal(SIGSEGV, SIG_DFL); 
  54. signal(SIGFPE, SIG_DFL); 
  55. signal(SIGBUS, SIG_DFL); 
  56. signal(SIGPIPE, SIG_DFL);    
  57. if ([[exception name] isEqual:UncaughtExceptionHandlerSignalExceptionName]) 
  58. kill(getpid(), [[[exception userInfo] objectForKey:UncaughtExceptionHandlerSignalKey] intValue]); 
  59. else 
  60. [exception raise]; 
  61. @end 
  62. NSString* getAppInfo() 
  63.     NSString *appInfo = [NSString stringWithFormat:@"App : %@ %@(%@)\nDevice : %@\nOS Version : %@ %@\nUDID : %@\n"
  64.                           [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"], 
  65.                           [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"], 
  66.                           [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"], 
  67.                           [UIDevice currentDevice].model, 
  68.                           [UIDevice currentDevice].systemName, 
  69.                           [UIDevice currentDevice].systemVersion, 
  70.                           [UIDevice currentDevice].uniqueIdentifier]; 
  71.     NSLog(@"Crash!!!! %@", appInfo); 
  72.     return appInfo; 
  73. void MySignalHandler(int signal) 
  74. int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount); 
  75. if (exceptionCount > UncaughtExceptionMaximum) 
  76. return
  77. NSMutableDictionary *userInfo = 
  78. [NSMutableDictionary 
  79. dictionaryWithObject:[NSNumber numberWithInt:signal] 
  80. forKey:UncaughtExceptionHandlerSignalKey]; 
  81. NSArray *callStack = [UncaughtExceptionHandler backtrace]; 
  82. [userInfo 
  83. setObject:callStack 
  84. forKey:UncaughtExceptionHandlerAddressesKey];    
  85. [[[[UncaughtExceptionHandler alloc] init] autorelease] 
  86. performSelectorOnMainThread:@selector(handleException:) 
  87. withObject: 
  88. [NSException 
  89. exceptionWithName:UncaughtExceptionHandlerSignalExceptionName 
  90. reason: 
  91. [NSString stringWithFormat: 
  92. NSLocalizedString(@"Signal %d was raised.\n" 
  93.                                           @"%@", nil), 
  94. signal, getAppInfo()] 
  95. userInfo: 
  96. [NSDictionary 
  97. dictionaryWithObject:[NSNumber numberWithInt:signal] 
  98. forKey:UncaughtExceptionHandlerSignalKey]] 
  99. waitUntilDone:YES]; 
  100. void InstallUncaughtExceptionHandler() 
  101. signal(SIGABRT, MySignalHandler); 
  102. signal(SIGILL, MySignalHandler); 
  103. signal(SIGSEGV, MySignalHandler); 
  104. signal(SIGFPE, MySignalHandler); 
  105. signal(SIGBUS, MySignalHandler); 
  106. signal(SIGPIPE, MySignalHandler); 

在應用自身的 didFinishLaunchingWithOptions 前,加入一個函數:

  1. - (void)installUncaughtExceptionHandler 
  2. InstallUncaughtExceptionHandler(); 

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

 

  1. [self InstallUncaughtExceptionHandler]; 

現在,基本上所有崩潰都能Hold住了。崩潰時將會顯示出如下的對話框:

這樣在崩潰時還能從容地彈出對話框,比起閃退來,用戶也不會覺得那么不爽。然后在下次啟動時還可以通過郵件來發送Crash文件到郵箱,這就看各個應用的需求了。

責任編輯:閆佳明 來源: cocoachina
相關推薦

2015-04-08 09:26:21

IT管理云計算基礎設施數據存儲

2020-07-08 08:22:08

FlutterSVGPNG

2019-08-28 07:28:13

React應用程序代碼

2020-11-06 08:13:03

服務器Nodejs客戶端

2021-01-18 13:17:04

鴻蒙HarmonyOSAPP

2021-01-28 14:53:19

PHP編碼開發

2009-11-20 11:52:10

2015-12-03 14:33:35

2021-10-28 06:17:46

架構設計組件

2018-06-20 11:00:06

云應用開發PaaS

2016-02-29 10:01:59

iosbug合理

2017-11-13 06:35:47

混合云應用程序DevOps

2022-07-11 14:53:37

微服務容器IT

2015-02-26 09:19:00

2022-05-11 10:58:11

MetricKitiOS13系統崩潰診斷

2022-07-13 13:29:56

微服務容器開發

2015-06-01 10:48:00

虛擬機云計算云就緒

2014-09-22 15:14:04

2017-04-28 09:04:32

移動應用開發反饋

2022-07-04 18:58:43

智能合約區塊鏈
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲区一| 国产精品a久久久久 | 九九热在线观看视频 | 永久看片| 国产免费一区 | av网站免费观看 | 成人在线精品视频 | 一区二区av在线 | 精品乱码一区二区三四区视频 | 亚洲综合久久久 | 久久大| 国产精品一区二区电影 | 免费观看a级毛片在线播放 黄网站免费入口 | 久久国产精品色av免费观看 | 国产91精品在线 | 最近最新中文字幕 | 成人国内精品久久久久一区 | 日韩美女一区二区三区在线观看 | 久久精品色欧美aⅴ一区二区 | 日韩欧美第一页 | 欧美成人不卡 | 激情免费视频 | 特黄特黄a级毛片免费专区 av网站免费在线观看 | 男女羞羞免费视频 | 色婷婷国产精品综合在线观看 | 丁香综合| 色综合久 | 欧美日韩不卡在线 | 日韩精品一区二区三区老鸭窝 | 嫩草视频免费 | 观看av| 操操日 | 精品一二区 | 国产精品福利网 | 日本一级淫片免费啪啪3 | 欧美九九| 欧美日韩在线视频一区 | 国产精品综合 | 国产欧美日韩一区二区三区在线 | aa级毛片毛片免费观看久 | 天堂中文字幕av |