[ios] 애플리케이션을 출시하기 전에 NSLog를 비활성화해야합니까?

iPhone 용 앱을 출시 할 때 비활성화 NSLog();하면 성능이 향상됩니까?



답변

이를 수행하는 한 가지 방법은 빌드 설정으로 이동하여 디버그 구성에서 다음과 같은 “전 처리기 매크로”값에 값을 추가하는 것입니다.

DEBUG_MODE=1

베타 또는 릴리스 버전이 아닌 디버그 구성에 대해서만이 작업을 수행해야합니다. 그런 다음 공통 헤더 파일에서 다음과 같이 할 수 있습니다.

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

이제 모든 곳 에서 NSLog 사용하는 대신 DLog. 테스트하고 디버깅 할 때 디버그 메시지를 받게됩니다. 베타 또는 최종 릴리스를 릴리스 할 준비가되면 모든 DLog행이 자동으로 비어 있고 아무것도 내보내지지 않습니다. 이렇게하면 변수를 수동으로 설정하거나 NSLogs필요한 주석을 달 필요가 없습니다. 빌드 대상을 선택하면 처리됩니다.


답변

Xcode 5 및 iOS 7 업데이트

참고 : 릴리스 빌드에서 print () 문 을 제거 하는 Xcode 7 / Swift 2.1 솔루션의 경우 여기에서 내 대답을 찾으 십시오 .

예, 릴리스 코드에서 NSLog 문을 제거해야합니다. 이는 코드 속도를 늦추고 릴리스 버전에서는 사용하지 않기 때문입니다. 다행히 Xcode 5 (iOS 7)에서는 릴리스 빌드에서 모든 NSLog 문을 ‘자동’으로 제거하는 것이 놀랍도록 간단합니다. 그러니 왜 그렇게하지 마십시오.

먼저 취해야 할 3 단계, 다음 몇 가지 설명

1) Xcode 프로젝트에서 ‘yourProjectName-prefix.pch’파일을 찾습니다 (일반적으로 main.m 파일이있는 ‘supporting files’그룹에서 찾을 수 있습니다.

2) ‘.pch’파일 끝에 다음 3 줄을 추가합니다.

#ifndef DEBUG
   #define NSLog(...);
#endif

3) ‘디버그’와 ‘출시’버전의 차이점을 테스트하십시오. 이를 수행하는 한 가지 방법은 ‘구성표 편집’-> ‘앱 이름 실행’-> ‘정보’탭에서 디버그와 릴리스 사이의 드롭 다운 상자를 사용하여 선택하는 것입니다. 릴리스 버전에서는 디버그 콘솔에 NSLog 출력이 표시되지 않습니다!

이 모든 것이 어떻게 작동합니까?

우선, 전처리 기가 상대적으로 ‘멍청한’것이고 컴파일러가 호출되기 전에 ‘텍스트 대체자’역할을한다는 것을 알아야합니다. ‘#define’은 #define명령문 뒤에 오는 것으로 대체 합니다.

#define NSLog(...);

(...)괄호 사이에 ‘무엇이든'()를 의미합니다. ;끝에 도 마음 . 이것은 컴파일러가 이것을 최적화하기 때문에 꼭 필요한 것은 아니지만 더 ‘정확’하기 때문에 거기에 두는 것을 좋아합니다. 우리의 후 #define처리기가 ‘아무것도’로 대체됩니다, 그래서 그것은 단지에서 시작하여 전체 라인을 버리지 않도록, ‘아무것도’없다 NSLog...때까지와를 포함 ;.

define 문은 #ifdef(정의 된 경우) 또는 #ifndef(정의되지 않은 경우 )를 사용하여 조건부로 만들 수 있습니다.

여기서 우리 #ifndef DEBUG는 ‘디버그 기호가 정의되지 않은 경우’를 의미합니다. #ifdef또는 #ifndef될 필요가와 ‘폐쇄’#endif

Xcode 5는 기본적으로 빌드 모드가 ‘DEBUG’일 때 ‘DEBUG’기호를 정의합니다. ‘릴리스’에서는 정의되지 않았습니다. 프로젝트 설정에서 ‘빌드 설정’탭-> ‘Apple LLVM 5.0-전처리’섹션으로 스크롤-> 전 처리기 매크로에서이를 확인할 수 있습니다. 릴리스 빌드에 대해 ‘DEBUG’기호가 정의되지 않았 음을 알 수 있습니다!

마지막으로 .pch 파일은 Xcode에 의해 자동으로 생성되며 컴파일 시간 동안 모든 소스 파일에 자동으로 포함됩니다. 따라서 #define각 소스 파일에 모든 것을 넣은 것과 같습니다 .


답변

위의 거의 모든 답변은 해결책을 제시하지만 문제를 설명하지는 않습니다. 나는 구글에서 검색을했고 그 이유를 찾았다. 내 대답은 다음과 같습니다.

예, 릴리스 버전에서 NSLog를 주석 처리하면 성능이 향상됩니다. NSLog는 매우 느리기 때문입니다. 왜? NSLog는 1) Apple System Logging (ASL)에 로그 메시지를 기록하고, 2) 앱이 xcode에서 실행되는 경우 stderr에도 기록합니다.

주요 문제는 첫 번째 문제에 있습니다. 스레드 안전을 달성하기 위해 NSLog가 호출 될 때마다 ASL 시설에 대한 연결을 열고 메시지를 보내고 연결을 닫습니다. 연결 작업은 매우 비쌉니다. 또 다른 이유는 NSLog가 기록 할 타임 스탬프를 가져 오는 데 시간을 소비하기 때문입니다.

여기 에서 참조 .


답변

개인적으로 가장 좋아하는 것은 가변 매크로를 사용하는 것입니다.

#ifdef NDEBUG
    #define NSLog(...) /* suppress NSLog when in release mode */
#endif


답변

NSLog()프로덕션에서 전혀 전화하지 않는 것이 약간 더 빠르게 실행 된다는 현명하게 언급 한 모든 사람들과 더불어 다음과 같이 추가 하겠습니다.

이러한 모든 NSLog()출력 문자열은 스토어에서 앱을 다운로드하고 Xcode를 실행하는 Mac에 연결된 장치로 실행하는 모든 사람에게 표시됩니다 (Organizer 창을 통해).

기록하는 정보에 따라 (특히 앱이 서버에 연결하거나 인증하는 경우 등) 심각한 보안 문제가 될 수 있습니다 .


답변

프로젝트 기본 설정

Xcode에서 프로젝트의 현재 기본 설정 내에서 NS_BLOCK_ASSERTIONS매크로는 릴리스 버전과 DEBUG=1디버그 버전에서 1로 설정됩니다 .

그래서 저는 다음과 같은 방법을 선호합니다.

// NS_BLOCK_ASSERTIONS is defined by default, as shown in the screenshot above.
// Or, you can define yourself Flags in the `Other C Flags` -> `Release`.
#ifndef NS_BLOCK_ASSERTIONS
    #define _DEBUG
#endif

#ifdef _DEBUG
// for debug mode 
#define DLog(fmt,...) NSLog(@"%s " fmt, __FUNCTION, ##__VA_ARGS__) 
... /// something extra
#else
// for release mode
#define DLog(fmt,...) /* throw it away */
... /// something extra
#endif


답변

예, 비활성화해야합니다. 특히 코드 속도를 극대화하려는 경우. NSLogging은 왼쪽과 오른쪽으로 다른 개발자가 파헤 치려고 할 수있는 시스템 로그를 오염시키고 속도가 중요한 코드 (루프 내부 등)에 큰 영향을 미칠 수 있습니다. 실수로 재귀 함수에 일부 로그 메시지를 한 번 남겼습니다. “30 % 속도 향상!”으로 업데이트를 출시해야합니다. 몇 주 후 … 😉