Objective-C : 어설 션 vs. 예외 vs. 오류


79

Cocoa에서 언제 NSAssert, NSException, NSError를 사용해야합니까?

내가 생각한 것은 다음과 같습니다.

NSAssert- 프로그래머에게 사용되는 클라이언트 프로그램을 만들 때 규칙, 규칙, 가정 또는 사전 조건과 사후 조건을 다시 확인하는 이점이 있습니까?

NSException- 라이브러리를 사용하는 다른 프로그래머의 이익을 위해 타사 라이브러리를 만들 때 입력이 유효하지 않은 경우 즉시 알 수 있습니까?

NSError- 결과가 보장되지 않는 파일, 데이터베이스 또는 웹 서비스와 같은 데이터를 얻기 위해 외부 시스템과 인터페이스 할 때?

답변:


103

NSAssert이 실패하면 예외가 발생합니다. 따라서 NSAssert는 코드에서 작성한 가정을 작성하고 확인하는 짧고 쉬운 방법입니다. (내 의견으로는) 예외의 대안이 아니라 지름길 일뿐입니다. 어설 션이 실패하면 코드에서 심각한 문제가 발생한 것이므로 프로그램을 계속해서는 안됩니다.

한 가지 주목할 점은 NSAssert는 릴리스 빌드에서 코드로 컴파일되지 않으므로 일반적으로 개발 중에 온 전성 검사에 사용됩니다. 저는 실제로 항상 활성화 된 사용자 지정 assert 매크로를 사용하는 경향이 있습니다.

@throw자신의 NSException 이 발생 하는 시간 은 릴리스 빌드에서 확실히 원할 때와 일부 인수가 유효하지 않거나 잘못 호출 된 경우 공용 라이브러리 / 인터페이스와 같은 경우입니다. @catch예외 에 대한 표준 관행이 아니라는 점에 유의하고 애플리케이션을 계속 실행하십시오. 일부 Apple의 표준 라이브러리 (예 : Core Data)로 이것을 시도하면 나쁜 일이 발생할 수 있습니다. 어설 션과 유사하게 예외가 발생하면 어딘가에 프로그래밍 오류가 있음을 의미하므로 일반적으로 앱이 상당히 빨리 종료되어야합니다.

NSErrors 는 프로그래밍 오류가 아니고 복구 할 수있는 오류에 대해 라이브러리 / 인터페이스에서 사용해야합니다. 호출자에게 정보 / 오류 코드를 제공하면 오류를 깔끔하게 처리하고 적절한 경우 사용자에게 경고하고 실행을 계속할 수 있습니다. 이는 일반적으로 파일을 찾을 수 없음 오류 또는 기타 치명적이지 않은 오류와 같은 것입니다.


15
더 강력하게 말하면 NSException 을 사용하여 복구 가능한 오류를 나타내지 않아야합니다.
bbum

28
즉, Obj-C의 NSException == Java의 Error 클래스, Obj-C의 NSError == Java의 Exception 클래스입니다. 일관성을 위해 만세!
Tustin2121

2
실제로 미리 컴파일 된 접두사 파일에 NS_BLOCK_ASSERTIONS를 추가하지 않으면 NSAssert가 코드로 컴파일됩니다. 읽기 대답은 아래를 (단지 :) 지금 칭찬하기 (50)를 얻을
likid1412

3

Cocoa의 관례는 예외가 프로그래머 오류를 나타내는 것입니다. 프레임 워크 코드를 포함한 많은 코드는 예외가 발생한 후 제대로 작동하도록 설계되지 않았습니다.

복구 할 수 있어야하는 모든 종류의 오류는 NSError. NSError사용자 에게 s를 표시하는 시스템도 있습니다 . 당신이 말했듯이 이것은 대부분 오류가있는 외부 자원에 유용합니다.

개념적으로 어설 션은 주어진 술어가 항상 참으로 평가된다는 진술입니다. 그렇지 않으면 프로그램이 중단됩니다. 동작을 수정할 수 있지만 NSAssert패밀리는 기본적으로 NSInternalInconsistencyExceptions 를 던지는 편리한 방법입니다 (릴리스 빌드에서 해제하는 옵션 포함).


2

편집 : Xcode 4.2에서는 릴리스 빌드에 대해 기본적으로 어설 션이 꺼져 있습니다.

이제 NSAssert는 릴리스 빌드에서 코드로 컴파일되지 않지만 빌드 설정에서 변경할 수 있습니다.


@ Mike Weller, 답변에 잘못된 것이 하나 있습니다.

한 가지 주목할 점은 NSAssert는 릴리스 빌드에서 코드로 컴파일되지 않으므로 일반적으로 개발 중 온 전성 검사에 사용됩니다.

실제로 미리 컴파일 된 접두사 파일을 추가하지 않으면 NSAssert가 코드로 컴파일됩니다NS_BLOCK_ASSERTIONS .

기술 노트 TN2190에서 다음을 찾을 수 있습니다.

C assert를 끄는 NDEBUG 또는 Foundation의 NSAssert를 끄는 NS_BLOCK_ASSERTIONS와 같은 매크로는 미리 컴파일 된 접두사 파일을 지정하는 데 중요합니다.

또는 다음을 읽을 수 있습니다. 릴리스 빌드에서 NSAssert가 비활성화되었는지 확인하는 방법?


1

일반적으로 예외는 프로그래머 오류를 알리는 데 사용되며 발생해서는 안되는 일입니다. 오류는 프로그램의 정상적인 작동에서 발생할 수있는 오류 조건 (기본적으로 사용자 오류 또는 참이어야하지만 그렇지 않을 수있는 외부 조건)을 알리는 데 사용됩니다. 따라서 문서에서 잠긴 요소를 삭제하는 것은 오류 일 수 있으며 인터넷 연결없이 파일을 다운로드하려고하면 오류가 발생하지만 컬렉션의 잘못된 요소에 액세스하려는 것은 예외입니다.

어설 션은 일반적으로 테스트에 사용되며 AFAIK는 다른 것과 같이 일반적인 오류 처리 메커니즘으로 사용되지 않습니다.


어설 션을 사용하여 불변성을 적용 할 수 있습니다. 예를 들어 NSParameterAssert(someParam != nil);는 지정된 매개 변수가 nil이 아니어야한다는 불변성을 강제합니다.
Lily Ballard

@Kevin Ballard : 어설 션은 일반적으로 릴리스 빌드에서 정의되거나 적어도 마지막으로 확인 했으므로 일반적인 오류 처리 메커니즘이 아니라고 말한 것처럼 말입니다.
Chuck

1
가능하지만 기본적으로 생략되지는 않습니다. 해당 동작을 얻으려면 빌드 설정을 변경해야합니다.
Lily Ballard
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.