development

글로벌 iPhone 예외 처리를 어떻게 구현합니까?

big-blog 2020. 12. 8. 18:53
반응형

글로벌 iPhone 예외 처리를 어떻게 구현합니까?


NSException을 발생시키는 iPhone 응용 프로그램에 충돌이 하나 있습니다. 충돌 보고서는 오류의 위치와 원인이 정확히 무엇인지 완전히 모호합니다. 원인을 확인하기 위해 어딘가에 최상위 예외 처리기를 설정하는 현명한 방법이 있습니까? 문제를 직접 재현 할 수는 없지만 베타 사용자 중 일부는 확실히 할 수 있습니다.

이러한 성격의 문제를 처리하는 현명한 방법은 무엇입니까?


여기에서 두 가지 질문을하는 것 같습니다. 최상위 수준 예외 처리기를 설정하는 방법; 근본 원인이 무엇인지 결정하는 문제를 처리하는 방법.

예외를 잡는 것은 몇 가지 다른 방법으로 수행 할 수 있지만이를위한 가장 좋은 방법은 NSSetUncaughtExceptionHandler를 사용하여 예외 처리기를 설정하는 것 같습니다.

앱에서 예외가 발생하면 기본 예외 처리기가 처리합니다. 이 핸들러는 앱이 종료되기 전에 콘솔에 메시지를 기록하는 것 이상을 수행하지 않습니다. 위에서 언급 한 함수를 사용하여 사용자 지정 예외 처리기를 설정하여이를 재정의 할 수 있습니다. 이를 수행하는 가장 좋은 위치는 앱 델리게이트 applicationDidFinishLaunching : 메소드입니다.

- (void)applicationDidFinishLaunching:(UIApplication *)application
{
    NSSetUncaughtExceptionHandler(&myExceptionHandler);
}

사용자 지정 처리기를 설정 한 후에는 원인이 무엇인지 확인하는 데 도움이되도록 기본 출력을 확장 할 수 있습니다.

void myExceptionHandler(NSException *exception)
{
    NSArray *stack = [exception callStackReturnAddresses];
    NSLog(@"Stack trace: %@", stack);
}

불행히도 OSX와 비교할 때 iPhone은 멋진 스택 추적을 생성하는 측면에서 상당히 제한적으로 보입니다. 위의 코드는 겉보기에 정크 출력을 생성합니다. 그러나 atos 도구를 통해이 출력을 실행할 수 있으며 여기에서 유용한 스택 추적을 생성 할 수 있어야합니다.

또 다른 옵션은 멋진 스택 추적을 자동으로 생성하는 데 도움 되는 이 기사 의 지침을 따르는 것입니다.

이것은 베타 테스터에게 제공되므로 작동하도록 조정해야 할 수도 있습니다.

당신은 문제를 스스로 복제 할 수 없었고 사용자들만 복제 할 수 있었다고 말합니다. 이 경우 Apple의 다음 기술 노트가 유용 할 수 있습니다.

https://developer.apple.com/library/content/technotes/tn2151/_index.html

업데이트 :이 게시물에는 여전히 유용한 정보가 포함되어 있지만 여기에 포함 된 일부 링크는 되돌릴 수 없습니다. 대체 게시물 의 정보를 사용하는 것이 좋습니다 .


혼자서 할 계획이라면 다음 접근 방식 중 하나를 사용할 수 있습니다.

접근 방식 1 :

void onUncaughtException(NSException* exception)
{
//save exception details
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  NSSetUncaughtExceptionHandler(&onUncaughtException);
  //Add coding to find if any exception has occurred from saved details if so send it to server or ask user to comment on the issue.
//Rest of the coding
}

접근 방식 2 :

void onUncaughtException(NSException* exception)
{

//Save exception details

}

int main(int argc, char *argv[])
{
    @autoreleasepool {

        NSSetUncaughtExceptionHandler(&onUncaughtException);

        return UIApplicationMain(argc, argv, nil, NSStringFromClass([SGGI_AppDelegate class]));
    }
}



-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
 {
      //Add coding to find if any exception has occurred from saved details if so send it to server or ask user to comment on the issue.
    //Rest of the coding
 }

Approcach3 :

int main(int argc, char *argv[])
{
    @autoreleasepool {

        @try {

            return UIApplicationMain(argc, argv, nil, NSStringFromClass([SGGI_AppDelegate class]));
        }
        @catch (NSException *exception) {      
        //Save the exception
        }
        @finally {
        }

    }
}

-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
 {
      //Add coding to find if any exception has occurred from saved details if so send it to server or ask user to comment on the issue.
    //Rest of the coding
 }

노트 :

  • In my perspective don't try to send the exception details to server at the time of crashing send it when he starts the app again.

  • If you are going to use NSUserDefaults to save exception details then you have to synchronise it at the time of crashing otherwise it won't persist.

The following code snippet does the job.

   - (void)applicationWillTerminate:(UIApplication *)application
   {
       [[NSUserDefaults standardUserDefaults]synchronize];
   }
  • If you prefer to save it on sqlite db then it persists itself no need to call anything to persist at the time of crashing

In XCode, you should always set a global breakpoint for objc_exception_throw. Then you (usually) get a far more meaningful stack trace as to what is actually trying to throw an exception.

You can still get exceptions that originate in timer code or other places without your own code anywhere in the trace, but if you look at the method chain you can usually figure out generally what the exception is about (like having a notification sent where the target is gone).


Have you tried NSSetUncaughtExceptionHandler?


Another option for tracking crash reports is Plausible CrashReporter, open source code to automatically send you crash reports from the field.

There's also the CrashReporterDemo, another open source option that is a combination of Plausible CrashReporter and some server code to better track crash reports.

And lastly, there's MacDevCrashReporter, a service that appears to have similarities to iOSExceptional.com, suggested in another answer. I have no idea what their terms of service are, as I've not signed up for the beta. Definitely worth checking before getting in too deeply.


Check out Crittercism. It goes above and beyond what you're asking of here in that it lets you get this information for all users using your app, so you should be able to see your own crash.

You can also upload the DYSM for your particular build and it will automatically symbolicate the crash for you on their website. That should provide you with the clearest stack-trace without being hooked up to the debugger.

You might also want to make sure you are set to break on Objetive-C exceptions. In Xcode 4, in the breakpoints tab, you can add a Breakpoint Exception that breaks on both/either C++ and Obj-C exceptions. Without this on, most stack traces for exceptions thrown are pretty unhelpful.

Good luck!

참고URL : https://stackoverflow.com/questions/1282364/how-do-you-implement-global-iphone-exception-handling

반응형