[iphone] 프로덕션 코드에서 NSLog ()를 사용해서는 안된다는 것이 사실입니까?

나는이 사이트에서 이것을 몇 번 들었지만 이것이 사실인지 확인하고 싶었다.

내 코드 전체에 NSLog 함수 호출을 뿌릴 수있을 것으로 기대했으며 릴리스 / 배포 빌드를 빌드 할 때 Xcode / gcc가 해당 호출을 자동으로 제거합니다.

이것을 사용하지 않아야합니까? 그렇다면 숙련 된 Objective-C 프로그래머들 사이에서 가장 일반적인 대안은 무엇입니까?



답변

전 처리기 매크로는 실제로 디버깅에 좋습니다. NSLog ()에는 아무런 문제가 없지만 더 나은 기능으로 자체 로깅 기능을 정의하는 것은 간단합니다. 여기에 내가 사용하는 것이 있는데, 여기에는 파일 이름과 줄 번호가 포함되어있어 로그 문을보다 쉽게 ​​추적 할 수 있습니다.

#define DEBUG_MODE

#ifdef DEBUG_MODE
    #define DebugLog( s, ... ) NSLog( @"<%p %@:(%d)> %@", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
    #define DebugLog( s, ... )
#endif

이 전체 문장을 자체 파일이 아닌 접두사 헤더에 넣는 것이 더 쉽다는 것을 알았습니다. 원하는 경우 DebugLog를 사용하여 일반 Objective-C 객체와 상호 작용하여보다 복잡한 로깅 시스템을 구축 할 수 있습니다. 예를 들어, 자체 로그 파일 (또는 데이터베이스)에 기록하고 런타임에 설정할 수있는 ‘priority’인수를 포함하는 로깅 클래스를 가질 수 있으므로 디버그 메시지는 릴리스 버전에 표시되지 않지만 오류 메시지는 ( 이 작업을 수행하면 DebugLog (), WarningLog () 등을 만들 수 있습니다.

아, #define DEBUG_MODE응용 프로그램의 다른 곳에서 재사용 할 수 있습니다. 예를 들어, 내 응용 프로그램에서 라이센스 키 확인을 비활성화하고 특정 날짜 이전의 응용 프로그램 만 실행하도록 허용하는 데 사용합니다. 이를 통해 최소한의 노력으로 시간이 제한적이고 완전한 기능을 갖춘 베타 사본을 배포 할 수 있습니다.


답변

-prefix.pch 파일의 끝에이 3 행을 넣으십시오.

#ifndef DEBUG
  #define NSLog(...) /* suppress NSLog when in release mode */
#endif

프로젝트 DEBUG를 만들 때 기본적으로 빌드 설정에 정의되어 있으므로 프로젝트에 아무것도 정의 할 필요가 없습니다 .


답변

NSLog 호출은 프로덕션 코드에 남겨 둘 수 있지만 실제로 예외적 인 경우 나 시스템 로그에 기록 될 정보에 대해서만 있어야합니다.

시스템 로그를 어지럽히는 응용 프로그램은 성가 시며 전문가가 아닙니다.


답변

Marc Charbonneau의 답변 에 대해서는 언급 할 수 없으므로이 답변으로 게시 할 것입니다.

사전 컴파일 된 헤더에 매크로를 추가하는 것 외에도 Target 빌드 구성을 사용하여 정의 (또는 정의 부족)를 제어 할 수 있습니다 DEBUG_MODE.

디버그 “활성 구성 을 선택하면 DEBUG_MODE정의되고 매크로가 전체 NSLog정의로 확장됩니다 .

은 “선택 해제 “활성 구성하는 것은 정의하지 않습니다 DEBUG_MODENSLog카는 릴리스 빌드에서 생략된다.

단계 :

  • 대상> 정보 입수
  • 빌드 탭
  • “전 처리기 매크로”(또는 GCC_PREPROCESSOR_DEFINITIONS) 검색
  • 구성 선택 : 디버그
  • 이 수준에서 정의 편집
  • 더하다 DEBUG_MODE=1
  • 구성 선택 : 릴리스
  • 확인 DEBUG_MODE이 설정되어 있지 않습니다GCC_PREPROCESSOR_DEFINITIONS

정의에서 ‘=’문자를 생략하면 전 처리기에서 오류가 발생합니다.

또한 매크로 정의 위에이 주석 (아래 그림 참조)을 붙여 넣어 DEBUG_MACRO정의의 출처 를 상기시킵니다 .)

// Target > Get Info > Build > GCC_PREPROCESSOR_DEFINITIONS
// Configuration = Release: <empty>
//               = Debug:   DEBUG_MODE=1


답변

편집 : Marc Charbonneau가 게시하고 sho 가 주목 한 방법 은 이 방법 보다 훨씬 낫습니다.

디버그 모드가 비활성화되었을 때 빈 기능을 사용하여 로깅을 비활성화하도록 제안한 답변 부분을 삭제했습니다. 자동 전 처리기 매크로 설정을 다루는 부분은 여전히 ​​관련이 있으므로 그대로 유지됩니다. Marc Charbonneau의 대답에 더 잘 맞도록 전 처리기 매크로의 이름도 편집했습니다.


Xcode에서 자동 (및 예상) 동작을 달성하려면 다음을 수행하십시오.

프로젝트 설정에서 “빌드”탭으로 이동하여 “디버그”구성을 선택하십시오. “전 처리기 매크로”섹션을 찾아 이름이 매크로를 추가하십시오 DEBUG_MODE.

편집 : 매크로로 로깅을 활성화 및 비활성화하는 Marc Charbonneau의 답변 을 참조하십시오 DEBUG_MODE.


답변

나는 매튜에 동의합니다. 프로덕션 코드에서 NSLog에는 아무런 문제가 없습니다. 실제로, 그것은 사용자에게 유용 할 수 있습니다. 즉, NSLog를 사용하는 유일한 이유가 디버그를 돕기 위해서라면 릴리스하기 전에 제거해야합니다.

또한이 질문을 iPhone 질문으로 태그 했으므로 NSLog는 리소스를 사용합니다. 이는 iPhone이 거의 소중하지 않은 것입니다. 있는 거 NSLogging의 당신이 만약 아무것도 귀하의 응용 프로그램에서 프로세서 시간을 빼앗아 아이폰에. 현명하게 사용하십시오.


답변

간단한 사실은 NSLog가 느리다는 것입니다.

그런데 왜? 이 질문에 대답하기 위해 NSLog가 무엇을하고 어떻게하는지 알아 봅시다.

NSLog는 정확히 무엇을합니까?

NSLog는 두 가지 작업을 수행합니다.

Apple 시스템 로깅 (asl) 기능에 로그 메시지를 기록합니다. 이렇게하면 Console.app에 로그 메시지가 표시 될 수 있습니다. 또한 응용 프로그램의 stderr 스트림이 터미널로 가는지 확인합니다 (예 : 응용 프로그램이 Xcode를 통해 실행될 때). 그렇다면 로그 메시지를 stderr에 기록합니다 (Xcode 콘솔에 표시됨).

STDERR에 쓰는 것이 어렵지 않습니다. 이것은 fprintf와 stderr 파일 디스크립터 참조로 달성 할 수 있습니다. 그러나 asl은 어떻습니까?

내가 ASL에 대해 발견 한 가장 좋은 문서는 피터 Hosey에서 10 일부 블로그 게시물입니다 : 링크

너무 자세하게 설명하지 않으면 서 (성능과 관련된) 주요 내용은 다음과 같습니다.

ASL 기능에 로그 메시지를 보내려면 기본적으로 ASL 데몬에 대한 클라이언트 연결을 열고 메시지를 보냅니다. 그러나 각 스레드는 별도의 클라이언트 연결을 사용해야합니다. 따라서 스레드 안전을 위해 NSLog가 호출 될 때마다 새 asl 클라이언트 연결을 열고 메시지를 보낸 다음 연결을 닫습니다.

리소스는 여기여기 에서 찾을 수 있습니다 .