runloop是OC當中最基本的一個知識點,本文主要從使用角度講述如何在應用運行中避免因程序異常致使的應用閃退。應用閃退是不少公司的噩夢,應用閃退會致使用戶的大量流失,因此控制程序的穩定性是當前不少公司技術團隊的首要任務。
且拋開控制bug根源問題,爲避免應用在不一樣環境下可能因一些不可預估的因素死掉,程序異常的處理措施便顯得尤其重要了。淺顯的說避免崩潰的根本原理是獲取到進程的異常,從而避免異常形成的程序crash,採用蘋果提供的進程監聽程序代碼以下:oop
// 監聽方法1 NSSetUncaughtExceptionHandler(&HandleException); // 監聽方法2 signal(SIGABRT, SignalHandler); signal(SIGILL, SignalHandler); signal(SIGSEGV, SignalHandler); signal(SIGFPE, SignalHandler); signal(SIGBUS, SignalHandler); signal(SIGPIPE, SignalHandler);
經過監聽方法在獲取到進程異常時觸發相關處理:
void HandleException(NSException *exception) {code
// 異常次數 int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount); if (exceptionCount > UncaughtExceptionMaximum) { return; } // 異常信息 NSArray *callStack = [LHLExceptionHelper backtrace]; NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithDictionary:[exception userInfo]]; [userInfo setObject:callStack forKey:UncaughtExceptionHandlerAddressesKey]; NSException *exceptionTemp = [NSException exceptionWithName:exception.name reason:exception.reason userInfo:userInfo]; // 個人處理 LHLExceptionHelper *exceptionHandler = [LHLExceptionHelper new]; [exceptionHandler performSelectorOnMainThread:@selector(makeException:) withObject:exceptionTemp waitUntilDone:YES];
}
記錄異常次數以及獲取異常信息等,最後經過獲取當前的runloop避免進程crash從而保證應用不閃退,固然也能夠告知用戶選擇退出應用避免所以產生的一些應用內的操做隱患,同時清空監聽信息,以便以後繼續循環。orm
(void)makeException:(NSException *)exception {進程
// 一直循環,等待退出命令
CFRunLoopRef runLoop = CFRunLoopGetCurrent();
CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);
while (!dismissed) {rem
for (NSString *mode in (__bridge NSArray *)allModes) { CFRunLoopRunInMode((CFStringRef)mode, 0.001, false); }
}it
// 清空
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);
}io