나는이 사이트에서 이것을 몇 번 들었지만 이것이 사실인지 확인하고 싶었다.
내 코드 전체에 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_MODE
와 NSLog
카는 릴리스 빌드에서 생략된다.
단계 :
- 대상> 정보 입수
- 빌드 탭
- “전 처리기 매크로”(또는
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 클라이언트 연결을 열고 메시지를 보낸 다음 연결을 닫습니다.