실제로 NSAssert의 요점은 무엇입니까?


155

내가 알고있는 것은 : 단언이 실패하면 앱이 충돌한다는 것입니다. 이것이 NSAssert를 사용하는 이유입니까? 아니면 다른 장점은 무엇입니까? 그리고 -1을 매개 변수로받지 않아야하지만 -0.9 또는 -1.1 일 수있는 함수와 같이 코드에서 만든 가정 위에 NSAssert를 배치하는 것이 옳습니까?

답변:


300

주장은 가치가 예상대로 이루어 지도록하는 것입니다. 어설 션이 실패하면 문제가 발생하여 앱이 종료 된 것입니다. assert를 사용하는 한 가지 이유는 전달 된 매개 변수 중 하나가 정확히 일부 값 (또는 값 범위)이 아닌 경우 동작하지 않거나 매우 나쁜 부작용을 일으키는 기능이있는 경우 만들 수 있습니다. 가치가 당신이 기대하는 값인지 확인하십시오. 그렇지 않으면 뭔가 잘못되어 앱이 종료됩니다. Assert는 디버깅 / 단위 테스트 및 사용자가 "악한"일을하지 않도록하는 프레임 워크를 제공 할 때 매우 유용 할 수 있습니다.


9
릴리스를 위해 NSAssert를 꺼내야합니다. 컴파일 타임 플래그가 있습니다.
Barry Wark

127
> NSAssert를 릴리스해야합니다. 이것은 논쟁의 여지가 있습니다. 필자는 항상 어설 션이 활성화 된 상태로 응용 프로그램을 출시하며 이는 많은 소프트웨어에 대한 표준 관행입니다. 예를 들어 Apple은이를 수행합니다. 프로그램이 비정상 상태를 감지하자마자 충돌해야합니다. 오류가 발생한 위치의 스택 추적을 얻을 수 있지만 어설 션을 비활성화하면 메모리 및 / 또는 사용자 데이터가 손상되어 문제를 디버깅하기가 매우 어려울 수 있습니다.
Mike Weller

18
XCode 4에는 릴리스 구성에서 기본적으로 NS_BLOCK_ASSERTIONS가 정의되어 있습니다. 릴리스 된 코드에 NSAssert : s가 포함되지 않도록 변경하지 않으면
Jonny

16
올바르게 이해하면 (릴리스 버전에서) 두는 요점은 무엇입니까? 왜으로 NSAssert를 대체하지 진술 경우, 그리고 만약 (뭔가 끔찍한 일이) 다음 사용자에게 알려 (또는 아래에 뭔가 할 당신의 ... 제어)뿐 아니라 종료 / 충돌과 무슨 일이 있었는지 궁금 사용자를 떠나거나 뭔가 빠졌습니까?
Gik

11
정상적인 상황에서는 전혀 발생하지 않는 모든 예외적 인 상황을 해결하는 데 개발자 시간이 낭비됩니다. 여기에는 각 사용자에게 사용자에게 알리고 / 또는 앱이 발생한 후 예상대로 수행 할 수 있도록 앱을 강력하게 만드는 적절한 방법을 고려해야합니다. 보다 실용적인 방법은 앱을 중단하고 충돌 보고서에서 발견 된 버그를 수정하고 새 버전을 출시하는 것입니다. 그러나 이러한 상황에서 데이터 손실이 없는지 확인하는 것이 중요합니다. 그럼에도 불구하고 이것은 보장되어야하지만 훨씬 적은 작업입니다.
trss

20

NSAssert와 실제로 대화 할 수는 없지만 C의 assert ()와 유사하게 작동한다고 생각합니다.

assert ()는 코드에서 시맨틱 계약을 시행하는 데 사용됩니다. 그게 무슨 소리 야?

자, 당신이 말한 것과 같습니다 : -1을 절대로받지 않아야하는 함수가 있다면 assert ()가 다음을 시행하도록 할 수 있습니다.

void gimme_positive_ints (int i) {
  주장 (i> 0);
}

이제 오류 로그 (또는 STDERR)에 다음과 같은 내용이 표시됩니다.

어설 션 i> 0 실패 : 파일 example.c, 2 행

따라서 잠재적으로 잘못된 입력을 방지 할뿐만 아니라 유용한 표준 방식으로 기록합니다.

그리고 적어도 C에서는 assert ()가 매크로이므로 릴리스 코드에서 assert ()를 no-op로 다시 정의 할 수 있습니다. NSAssert (또는 더 이상 assert ())의 경우인지는 모르겠지만 해당 검사를 컴파일하는 것이 매우 유용했습니다.


2
예, NSAssert도 매크로입니다.
Martin Wickman

18

NSAssert앱을 다운시키는 것 이상을 제공합니다. 클래스, 메소드 및 어설 션이 발생한 행을 알려줍니다. NS_BLOCK_ASSERTIONS를 사용하여 모든 어설 션을 쉽게 비활성화 할 수 있습니다. 따라서 디버깅에 더 적합합니다. 반면에 던지면 NSException앱이 충돌합니다. 또한 예외의 위치에 대해서는 알려주지 않으며 간단하게 비활성화 할 수 없습니다. 아래 이미지의 차이점을 참조하십시오.

NSAssert 설명서에 설명 된 대로 어설 션에서도 예외가 발생하므로 앱이 중단 됩니다.

호출되면 어설 션 핸들러는 메소드 및 클래스 이름 (또는 함수 이름)을 포함하는 오류 메시지를 인쇄합니다. 그런 다음 NSInternalInconsistencyException 예외가 발생합니다.

NSAssert :

어설 션 후 로그

NSException :

예외 후 로그


NSException그것이를 통해 반환 출력 사용자 정의 할 수 많은 기회 제공 reasonuserInfo매개 변수를. 클래스 이름, 선택기, 줄 정보 및 디버깅을 돕기 위해 추가해야 할 항목을 추가 할 수 없었습니다. IMHO는 NSAssert개발 중에 디버깅 목적으로 를 사용 하지만 배송을 비활성화합니다. NSException운송 코드에 명제를 남기고 싶다면를 던집니다 .
markeissler

17

모든 사람들이 위에서 말한 것 외에도 NSAssert()(C와 달리) 의 기본 동작은 assert()예외를 처리하여 잡을 수 있습니다. 예를 들어, Xcode가이를 수행합니다.


예외를 포착하고 처리하는 방법에 대한 자세한 내용이 있습니까?
Gon

1
코코아의 예외는 사실상 "잡을 수 있고 처리 할 수있는"것이 아닙니다. 콜 트리의 어느 곳에서나 컨트롤이 애플 함수를 통과하면 동작이 정의되지 않습니다. 예외는 순전히 오류보고 (일명, 기준 등)에 대한 것이며 Java와 같은 일반적인 용도에는 사용되지 않습니다.
Michael

9

누군가가 언급했지만 완전히 설명하지 않은 것처럼 명확히하기 위해 사용자 정의 코드를 작성하는 대신 어설 션을 사용하고 사용하는 이유는 (예를 들어 if를 수행하고 잘못된 데이터에 대한 예외를 발생시키는) 프로덕션 애플리케이션에 대해 어설 션을 비활성화해야한다는 것입니다.

개발 및 디버깅 중에 오류를 포착 할 수있는 어설 션이 활성화됩니다. 어설 션이 false로 평가되면 프로그램이 중지됩니다. 그러나 프로덕션을 위해 컴파일 할 때 컴파일러는 어설 션 코드를 생략하고 실제로 프로그램 실행 속도를 높입니다. 그때까지 모든 버그를 수정했으면합니다. 생산 중에 프로그램에 여전히 버그가있는 경우 (어설 션이 비활성화되고 프로그램이 어설 션을 "스킵"하는 경우) 프로그램이 다른 지점에서 중단 될 수 있습니다.

NSAssert의 도움말에서 : "전 처리기 매크로 NS_BLOCK_ASSERTIONS가 정의되면 어설 션이 비활성화됩니다." 따라서 배포 대상에 매크로를 넣으면됩니다.


6

NSAssert(및 그 stdlib에 상응하는 assert)는 개발 중 프로그래밍 오류를 감지하는 것입니다. 프로덕션 (릴리스 된) 응용 프로그램에서 실패한 어설 션이 없어야합니다. 따라서 양의 인수가 필요한 메소드에 음수를 전달하지 않도록 주장 할 수 있습니다. 테스트 중에 어설 션이 실패하면 버그가있는 것입니다. 그러나 전달 된 값이 사용자에 의해 입력 된 경우 프로덕션의 어설 션에 의존하지 않고 입력에 대한 올바른 유효성 검사를 수행해야합니다 (비활성화 된 릴리스 빌드에 대해 #define을 설정할 수 있음) NSAssert*.


2
당신의 대답이 나에게 가장 의미가 있기 때문에 +1! NSAssert를 사용하면 출시 후가 아니라 개발 용으로 더 적합합니다. 허용되지 않는 값을 입력 한 사용자는 NSAssert가 응용 프로그램을 중단시키지 않고 UI 오류를 따라야합니다. 안개가 맑아졌습니다!
pnizzle

3

어설 션은 일반적으로 특정 방법이나 논리를 의도적으로 사용하도록하는 데 사용됩니다. 정수가 0보다 큰 2의 합을 계산하는 방법을 작성한다고 가정 해 봅시다. 방법이 항상 의도 한대로 사용되도록하려면 해당 조건을 테스트하는 어설 션을 설정해야합니다.

짧은 대답 : 코드가 의도 한 대로만 사용되도록 강요합니다.



2

그의 질문에 완전히 대답하기 위해 어떤 종류의 주장이든 디버깅을 돕는 것입니다. 소스에서 오류를 포착 한 다음 충돌을 일으킬 때 디버거에서 오류를 포착하는 것이 더 중요합니다.

예를 들어, 특정 범위의 값을 기대하는 함수에 값을 전달할 수 있습니다. 이 함수는 나중에 사용하기 위해 값을 저장하고 나중에 사용하면 응용 프로그램이 중단됩니다. 이 시나리오에서 볼 수있는 호출 스택에는 잘못된 값의 소스가 표시되지 않습니다. 누가 나쁜 가치를 전달하는지와 그 이유를 알아 내기 위해 나쁜 가치를 포착하는 것이 좋습니다.


-3

NSAssert조건과 일치하면 앱이 충돌합니다. 조건과 일치하지 않으면 다음 명령문이 실행됩니다. 아래 EX를 찾으십시오.

방금 작업이 무엇인지 테스트하는 앱을 만듭니다 NSAssert.

    - (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [self testingFunction:2];
}

-(void)testingFunction: (int)anNum{
    // if anNum < 2 -> the app will crash
    // and the NSLog statement will not execute
    // that mean you cannot see the string: "This statement will execute when anNum < 2"
    // into the log console window of Xcode
    NSAssert(anNum >= 2, @"number you enter less than 2");
    // If anNum >= 2 -> the app will not crash and the below 
    // statement will execute
    NSLog(@"This statement will execute when anNum < 2");
}

내 코드에 앱이 충돌하지 않으며 테스트 사례는 다음과 같습니다.

  • anNum > = 2-> 앱이 중단되지 않고 다음 로그 문자열을 볼 수 있습니다. "이 명령문은 outPut 로그 콘솔 창에"Num <2 "일 때 실행됩니다.
  • anNum <2-> 앱이 중단되고 다음과 같은 로그 문자열을 볼 수 없습니다 : "이 명령문은 anNum <2"

1
당신은 다른 방법으로 그것을 얻었다. "NSAssert는 조건과 일치 할 때 앱이 충돌합니다. 조건과 일치하지 않으면 다음 명령문이 실행됩니다." NSAssert가 조건과 일치하지 않으면 앱이 중단되고 조건과 일치하면 정상적으로 실행됩니다.
Joe Tam

앱이 조건을 충족하지 않으면 충돌이 발생하고 메시지가 로그되지 않으면 추가로 실행됩니다.
Pravin S.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.