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 이 생 겼 을 때 우리 가 정의 한 signal Handler 를 호출 하여 이상 을 처리 합 니 다.ps:NSSetUncaught ExceptionHandler 는 iOS SDK 에서 제공 하 는 기 존 함수 로 이상 을 포착 하 는 방법 으로 사용 하기에 편리 합 니 다.하지만 던 진 시그 널 을 잡 을 수 없어 시그 널 핸들 러 방법 을 정의 했다.
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 인자 가 들 어 옵 니 다.이상 을 가 져 오 면 캡 처 된 이상 을 최종 호출 처리 한 handle Exception 함수 에 전달 합 니 다.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!
"];
break;
case SIGILL:
description = [NSString stringWithFormat:@"Signal SIGILL was raised!
"];
break;
case SIGSEGV:
description = [NSString stringWithFormat:@"Signal SIGSEGV was raised!
"];
break;
case SIGFPE:
description = [NSString stringWithFormat:@"Signal SIGFPE was raised!
"];
break;
case SIGBUS:
description = [NSString stringWithFormat:@"Signal SIGBUS was raised!
"];
break;
case SIGPIPE:
description = [NSString stringWithFormat:@"Signal SIGPIPE was raised!
"];
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:@" , .
"]
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 수집 작업 을 할 수 있 습 니 다.원본 코드 다운로드
총결산
이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Swift의 패스트 패스Objective-C를 대체하기 위해 만들어졌지만 Xcode는 Objective-C 런타임 라이브러리를 사용하기 때문에 Swift와 함께 C, C++ 및 Objective-C를 컴파일할 수 있습니다. Xcode는 S...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.