나는이 사이트에서 이것을 몇 번 들었지만 이것이 사실인지 확인하고 싶었다.
내 코드 전체에 NSLog 함수 호출을 뿌릴 수있을 것으로 기대했으며 릴리스 / 배포 빌드를 빌드 할 때 Xcode / gcc가 해당 호출을 자동으로 제거합니다.
이것을 사용하지 않아야합니까? 그렇다면 숙련 된 Objective-C 프로그래머들 사이에서 가장 일반적인 대안은 무엇입니까?
나는이 사이트에서 이것을 몇 번 들었지만 이것이 사실인지 확인하고 싶었다.
내 코드 전체에 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
응용 프로그램의 다른 곳에서 재사용 할 수 있습니다. 예를 들어, 내 응용 프로그램에서 라이센스 키 확인을 비활성화하고 특정 날짜 이전의 응용 프로그램 만 실행하도록 허용하는 데 사용합니다. 이를 통해 최소한의 노력으로 시간이 제한적이고 완전한 기능을 갖춘 베타 사본을 배포 할 수 있습니다.
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
DEBUG_MODE
과 DEBUG_MACRO
틀에 얽매이지입니다. DEBUG_MACRO
애플 사이트 ( opensource.apple.com/source/gm4/gm4-15/src/m4.h?txt ) 에서 하나의 참조 만 찾았습니다 . 아마도 더 표준 DEBUG
적이고 NDEBUG
더 나은 선택일까요? NDEBUG
Posix에 의해 지정됩니다. while DEBUG
은 규칙에 의해 사용됩니다.
편집 : Marc Charbonneau가 게시하고 sho 가 주목 한 방법 은 이 방법 보다 훨씬 낫습니다.
디버그 모드가 비활성화되었을 때 빈 기능을 사용하여 로깅을 비활성화하도록 제안한 답변 부분을 삭제했습니다. 자동 전 처리기 매크로 설정을 다루는 부분은 여전히 관련이 있으므로 그대로 유지됩니다. Marc Charbonneau의 대답에 더 잘 맞도록 전 처리기 매크로의 이름도 편집했습니다.
Xcode에서 자동 (및 예상) 동작을 달성하려면 다음을 수행하십시오.
프로젝트 설정에서 "빌드"탭으로 이동하여 "디버그"구성을 선택하십시오. "전 처리기 매크로"섹션을 찾아 이름이 매크로를 추가하십시오 DEBUG_MODE
.
...
편집 : 매크로로 로깅을 활성화 및 비활성화하는 Marc Charbonneau의 답변 을 참조하십시오 DEBUG_MODE
.
간단한 사실은 NSLog가 느리다는 것입니다.
그런데 왜? 이 질문에 대답하기 위해 NSLog가 무엇을하고 어떻게하는지 알아 봅시다.
NSLog는 정확히 무엇을합니까?
NSLog는 두 가지 작업을 수행합니다.
Apple 시스템 로깅 (asl) 기능에 로그 메시지를 기록합니다. 이렇게하면 Console.app에 로그 메시지가 표시 될 수 있습니다. 또한 응용 프로그램의 stderr 스트림이 터미널로 가는지 확인합니다 (예 : 응용 프로그램이 Xcode를 통해 실행될 때). 그렇다면 로그 메시지를 stderr에 기록합니다 (Xcode 콘솔에 표시됨).
STDERR에 쓰는 것이 어렵지 않습니다. 이것은 fprintf와 stderr 파일 디스크립터 참조로 달성 할 수 있습니다. 그러나 asl은 어떻습니까?
내가 ASL에 대해 발견 한 가장 좋은 문서는 피터 Hosey에서 10 일부 블로그 게시물입니다 : 링크
너무 자세하게 설명하지 않으면 서 (성능과 관련된) 주요 내용은 다음과 같습니다.
ASL 기능에 로그 메시지를 보내려면 기본적으로 ASL 데몬에 대한 클라이언트 연결을 열고 메시지를 보냅니다. 그러나 각 스레드는 별도의 클라이언트 연결을 사용해야합니다. 따라서 스레드 안전을 위해 NSLog가 호출 될 때마다 새 asl 클라이언트 연결을 열고 메시지를 보낸 다음 연결을 닫습니다.
다른 답변에서 언급했듯이 #define을 사용하면 NSLog 사용 여부를 컴파일 타임에 변경할 수 있습니다.
그러나보다 유연한 방법은 Cocoa Lumberjack 과 같은 로깅 라이브러리를 사용하여 런타임시 무언가를 로깅할지 여부를 변경할 수 있습니다.
코드에서 NSLog를 DDLogVerbose 또는 DDLogError 등으로 바꾸고 매크로 정의 등을 위해 #import를 추가하고 종종 applicationDidFinishLaunching 메소드에서 로거를 설정하십시오.
NSLog와 동일한 효과를 얻으려면 구성 코드는
[DDLog addLogger:[DDASLLogger sharedInstance]];
[DDLog addLogger:[DDTTYLogger sharedInstance]];
보안 관점에서, 기록되는 내용에 따라 다릅니다. 경우 NSLog
(또는 다른 로거) 민감한 정보를 쓰고, 당신은 생산 코드에서 로거를 제거해야합니다.
감사의 관점에서 볼 때 감사인은 NSLog
중요한 정보를 기록하지 않도록 각 용도를보고 싶지 않습니다. 로거를 제거하라고 간단히 지시 할 것입니다.
나는 두 그룹과 함께 일합니다. 우리는 코드를 감사하고 코딩 가이드를 작성합니다. 우리 가이드는 프로덕션 코드에서 로깅을 비활성화해야합니다. 내부 팀은 시도하지 않는 것을 알고 있습니다.)
또한 실수로 민감한 정보가 유출되는 위험을 감수하고 싶지 않기 때문에 프로덕션에 로그인하는 외부 앱도 거부합니다. 우리는 개발자가 우리에게 말하는 것을 신경 쓰지 않습니다. 조사 할 시간이 아닙니다.
그리고 우리는 개발자가 아니라 '민감한'을 정의한다는 것을 기억하십시오.)
또한 내포 할 준비가 된 앱으로 많은 로깅을 수행하는 앱을 인식합니다. 너무 많은 로깅이 수행 / 필요한 이유가 있으며 일반적으로 안정성이 없습니다. 중단 된 서비스를 다시 시작하는 'watchdog'스레드가 있습니다.
보안 아키텍쳐 (SecArch) 검토를 해 본 적이 없다면, 이것들이 우리가 살펴본 것들입니다.
릴리스 코드에서 printf 또는 NSLog를 불필요하게 자세하게 설명해서는 안됩니다. 앱에 문제가있는 경우 printf 또는 NSLog 만 수행하십시오. IE는 복구 할 수없는 오류입니다.
로깅 (무료)에 TestFlight를 사용하는 것이 좋습니다. 이 방법을 사용하면 매크로를 사용하여 NSLog를 재정의하고 NSLog에 대한 기존의 모든 호출에 대해 서버, Apple 시스템 로그 및 STDERR 로그에 대한 로깅을 켜거나 끌 수 있습니다. 이에 대한 좋은 점은 사용자의 시스템 로그에 로그가 표시되지 않고 테스터에 배포 된 앱 및 App Store에 배포 된 앱에 대한 로그 메시지를 계속 검토 할 수 있다는 것입니다. 두 세계의 최고.