2010-11-30 3 views
8

내 친구 중 한 명이 iPhone Apps에서 NSException을 사용하지 말 것을 요청했습니다. 그가 준 이유는 "성능 병목 현상"이었습니다. 그러나 나는 그것에 대해 확신하지 못했습니다.iPhone Apps에서 NSException 사용

iPhone 앱에서 NSException을 사용하는 것을 제게 확인시켜 줄 사람이 있습니까? NSException 사용에 대한 모범 사례가있는 경우이를 제공하십시오.

UPDATE :

link 우리가 응용 프로그램 레벨에서 예외 처리를 사용하도록 요청합니다. 누군가 그것을 해본 적이 있습니까? 이 제품의 장점과 다른 성능 향상 장치를 제공하십시오.

답변

30

:

복구 할 수없는 오류

사용하기에만 적합

하지만 아무것도 나타 내기 위해 예외를 사용하지 마십시오 @ 복구 할 수없는 오류를 다루는 @ 캐치 /보십시오. @ throw/@ try/@ catch를 사용하여 iOS 또는 Mac OS X에서의 조작과 같은 제어 흐름을 수행하는 것은 결코 적절하지 않습니다. 그렇더라도 복구 할 수없는 오류를 나타내는 예외를 사용하는 것이 더 좋은지 아니면 단순히 충돌 (call abort()); 충돌은 종종 훨씬 더 많은 증거를 남깁니다.

예를 들어, 범위를 벗어나는 예외를 잡는 것이 목표를 잡는 것이고 오류를보고하는 것이 아니라면 - 일반적으로 - 충돌하거나 적어도 경고합니다 사용자가 귀하의 앱이 일관성없는 상태에 있으며 데이터가 손실 될 수 있음을 알립니다.

시스템 프레임 워크 코드를 통해 발생한 모든 예외 동작은 정의되지 않습니다.


당신은 " 프레임 워크 코드가 정의되지 않은 시스템을 통해 슬로우 예외의 행동을."설명 할 수 안에 세부 사항?

확실히.

시스템 프레임 워크는 모든 예외가 치명적이고 복구 불가능한 오류로 간주되는 디자인을 사용합니다. 모든 의도와 목적을 위해 프로그래머 오류. 이 규칙에는 매우 제한된 수의 예외 (heh)가 있습니다.

따라서 구현시 시스템 프레임 워크 코드는 시스템 프레임 워크 코드를 통과하는 예외가 던져지면 모든 것이 올바르게 정리되지 않도록합니다. 사인 예외적으로, 정의에 의해, 복구 할 수없는 이유는 정리 비용을 지불?

your-code-1() 
    system-code() 
     your-code-2() 

즉 :

이 호출 스택을 고려 코드에서 더 많은 코드를 호출하는 시스템 코드로 코드를 호출하는 코드 (매우 일반적인 패턴이지만 호출 스택이 분명히 훨씬 더 깊음).

your-code-2이 예외를 throw하는 경우 예외가 전달되는 경우 system-code은 동작이 정의되지 않았 음을 의미합니다. system-code은 응용 프로그램을 정의되지 않았거나 잠재적으로 크래시 또는 데이터 손실이 많은 상태로 둡니다.

또는 더 강력하게 : your-code-1에서 잡아서 처리 할 수 ​​있다고 예상하여 your-code-2에 예외를 throw 할 수 없습니다.

+0

"시스템 프레임 워크 코드를 통해 throw 된 예외의 동작이 정의되지 않았습니다." 상세히? – Krishnan

+0

질문 업데이트 .... – Krishnan

+0

+1, 좋은 one.Can 유 제발 예외에 관한 내 가정은 올바른지 않습니다. 특정 예외의 경우에는 NSException을 사용하면 (바인딩 밖으로) 가정합니다. 예외를 확인하기위한 모든 클래스. 응답하십시오. – Ishu

0

일반적으로 오류를 알리려고하는지 또는 실제로 예외적 인 조건이 있는지 스스로에게 물어보십시오. 전자의 경우 성능 문제와 상관없이 매우 나쁜 아이디어입니다. 실제 또는 인식됩니다. 후자의 경우 가장 확실하게해야 할 일입니다. 한마디로

+2

아니요. iOS의 예외는 복구 할 수없는 오류입니다. – bbum

+1

저에게 복구 할 수있는 상황은 오류입니다 :) – jer

6

꽤 많이 사용하는 audio app에 예외 처리를 사용했습니다. 많은 독서와 약간의 벤치마킹 및 분해 분석을 한 후에, 나는 (지능적으로) 그들을 사용하지 않는 진짜 이유가없고 (NSError 포인터 포인터, 끝이없는 조건문 ...) 많은 이유가 없다는 논쟁적인 결론에 도달했습니다. 왝!). 사람들이 포럼에서 말하는 대부분은 Apple Docs를 반복하는 것입니다.

내가 this blog post에서 자세히 꽤 들어갈하지만 난 여기에 내 결과를 간략하게 설명합니다 : @ (CPU의 측면에서) @ 캐치가/@ 마침내 너무 비싸/시도 :

신화 1

내 iPhone 4에서는 1 백만 건의 예외를 던지고 잡는 데 약 8.5 초가 걸립니다. 이는 각각 약 8.5 마이크로 초에 불과합니다. CoreAudio 실시간 스레드에서 비용이 많이 듭니까? 어쩌면 약간의 (그러나 당신은 예외를 던지지 않을 것입니다.)하지만, UIAlert에서 8.5 초의 지연으로 인해 사용자가 파일을 여는 데 문제가 있다는 것을 알았습니까?

신화 2 : @try 블록은 32 비트가 비용을 지불해야한다는

애플의 워드 프로세서 및 상태 "64 비트에 제로 비용 @try 블록"말하는 32 비트 iOS에서 비용이 되세요. 약간의 벤치마킹 및 디스 어셈블리 분석은 32 비트 iOS (ARM 프로세서)에서도 제로 비용의 @try 블록이 있음을 나타냅니다. 애플이 32 비트를 말하려고 했습니까 ?

신화 3 : 그것은 코코아 프레임 워크를 통해 슬로우 예외가

예, 그들은 "정의"입니다 정의되지 않은,하지만 당신은 어쨌든 애플 프레임 워크를 통해 던지는 무엇을하고 있는지 사항? 물론 애플은 그들을 위해 처리하지 않습니다. 복구 가능한 오류에 대한 예외 처리를 구현하는 요점은 로컬에서 처리하는 것입니다.

한쪽 가장자리의 경우는 NSObject:performSelectorOnMainThread:waitUntilDone:과 같은 방법입니다. 나중에 매개 변수가 YES이면이 함수는 동기 함수처럼 작동합니다.이 경우 예외가 호출 범위 위로 버블 링 될 것으로 예상 할 수 있습니다. 예외가 (메인 스레드의 실행 루프) 귀하의 캐치 누락 및 충돌 "코코아 프레임 워크를 통해"통과 것이다이 경우

///////////////////////////////////////////////////////////////////////// 
#pragma mark - l5CCThread 
///////////////////////////////////////////////////////////////////////// 

@interface l5CCThread : NSThread @end 

@implementation l5CCThread 

- (void)main 
{ 
    @try { 

     [self performSelectorOnMainThread:@selector(_throwsAnException) withObject:nil waitUntilDone:YES]; 

    } @catch (NSException *e) { 
     NSLog(@"Exception caught!"); 
    } 
} 
- (void)_throwsAnException { @throw [NSException exceptionWithName:@"Exception" reason:@"" userInfo:nil]; } 

@end 

///////////////////////////////////////////////////////////////////////// 
#pragma mark - l5CCAppDelegate 
///////////////////////////////////////////////////////////////////////// 

@implementation l5CCAppDelegate 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    l5CCThread *thd = [[l5CCThread alloc] init]; 
    [thd start]; 

    return YES; 
} 
// ... 

예를 들면 다음과 같습니다. GCD의 dispatch_synch을 사용하면 쉽게이 문제를 해결할 수 있으며 메서드 호출에 예외 처리를 더한 블록 인수를 넣을 수 있습니다.

사용하는 이유 NSException의 이제까지 코어 오디오와 같은 기존의 C 기반 프레임 워크 중 하나에 작업을 끝낼 NSError의

누구나 그것을 확인, 처리 및 오류를보고 무엇을 기계에 의존 알고있는 이상. @ try/@ catch와 NSExceptions가 제공하는 주된 이점은 코드를보다 깔끔하고 쉽게 유지할 수있게하는 것입니다.

파일에 대해 5 줄의 코드가 있다고 가정 해보십시오. 각각은 3 가지 다른 오류 (예 : 디스크 공간 부족, 읽기 오류 등) 중 하나를 던질 수 있습니다. NO 회귀 값을 검사하는 조건의 각 줄을 래핑하는 대신 NSError 포인터 조사를 다른 ObjC 메서드 (또는 더 나쁜 경우 #define 매크로를 사용)보다 아웃소싱하는 대신 에 5 줄을 모두 @ try와 바로 각 오류를 처리하십시오. 당신이 구할 줄을 생각해보십시오!

NSException 하위 클래스를 만들면 오류 메시지를 쉽게 중앙에서 관리 할 수 ​​있으며 코드를 깔끔하게 정리할 필요가 없습니다. 치명적인 프로그래머 오류 (예 : NSAssert)에서 앱의 "치명적이지 않은"예외를 쉽게 구별 할 수도 있습니다. 또한 "name"상수 (서브 클래스의 이름은 "이름")에 대한 필요성을 피할 수 있습니다. 벤치 마크 및 분해에 대한

모든이의 예 자세한 내용은, 캐치/마침내 거의가 다른 모든 주요 언어를 사용하는 패러다임 (C++, 자바, PHP는/...

예외 on this blog post 더하기 시도 루비, 파이썬). 아마도 편집증을 삭제하고 그것을 받아 들일 시간이 될 것입니다 ... 적어도 iOS에서는.

+6

NSExceptions를 복구 가능한 오류 및 흐름 제어에 사용하는 것이 좋다고 제안하는 것은 올바르지 않습니다. 프레임 워크는 명시 적으로 이것을 지원하지 않습니다. – bbum

+0

(더 중요한) 요점을 제외하고는 필자가 원하는 것이 모두 회복되지 않으면 조기에 자주 돌아 오는 것이 좋다. 캐치 캐스케이드가 있다면 어때요? – danyowdee

+2

각 오류 유형 처리를 한 줄에 처리하지 않고 코드 블록별로 한 곳으로 집중 처리 할 수 ​​있습니다. –