출처 : http://reysion.tistory.com/19
디버깅시 유용한 팁이다.
우리는 로그를 출력할 때 NSLog를 사용하는데 파일명과 함수명 그리고 라인넘버를 출력하려면 다음과 같은 코드를 쓰면된다.
NSLog(@"%s :: %s :: %d" , __FILE__,__FUNCTION__,__LINE__);
위처럼 로그를 찍으면 해당 소스파일의 위치와 라인을 Debugger Console에서 다음과 같이 출력해 준다.
[Session started at 2011-01-24 17:03:41 +0900.]
2011-01-24 17:03:47.009 adidas[2614:207] /Users/reysion/Documents/ex/Classes/LoginView.m :: -[LoginView loginAction] :: 44
LoginView.m 파일(loginAction함수)의 44라인에서 찍은 로그라는 것을 알수 있다.2011-01-24 17:03:47.009 adidas[2614:207] /Users/reysion/Documents/ex/Classes/LoginView.m :: -[LoginView loginAction] :: 44
여기서 한발 더 나아가보자.
디버그 모드일 때만 로그 메시지를 보여주고 중복되는 부분을 생략해서 쉽게 로그코드를 작성할 수 없을까?
메크로를 사용하면 쉽게 해결된다.
OtherSources폴더에 있는 [프로젝트명]_prefix.pch 파일에 다음과 같이 메크로를 만든다.
#ifdef DEBUG
#define NSLog( s, ... ) NSLog( @"[%@ %s(%d)] %@", [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __PRETTY_FUNCTION__, __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
#define NSLog( s, ... )
#endif
#define NSLog( s, ... ) NSLog( @"[%@ %s(%d)] %@", [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __PRETTY_FUNCTION__, __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
#define NSLog( s, ... )
#endif
위 메크로의 내용은 Build Configuration이 Debug 일때만 NSLog를 출력하며
그 출력 값은 파일명, 함수명, 라인넘버이고 포맷은 "[파일명 함수명(라인넘버)]" 형태로 출력된다는 내용이다.
세부적으로 파일명을 "__FILE__"을 써서 그냥 출력하면 파일의 위치경로까지 출력되기 때문에 로그가 지져분해지고 가독성이 떨어지게 된다.
그래서 lastPathComponent를 써서 파일명만 출력하게 하였다.
Build Configuration이 Debug일 때라는 것은 디버그 모드일 때 즉 project Info -> Build 창에서 Configuration이 Debug로 설정 되었을 때를 말하며
Build Setting에서 "OTHER_CFLAGS" 값을 "-DDEBUG=1"로 설정해 줘야 위에서 정의한 메크로를 사용할 수 있다.
설정 방법은검색바에 "OTHER_CFLAGS"를 검색해서 값을 수정해 주면 된다.
만약에 없다면 좌측 하단에 톱니바퀴 버튼을 클릭하여 Add User-Defined Setting에서 "OTHER_CFLAGS" 항목을 추가하고 값을 입력하면 된다.
다음은 메크로를 이용하여 NSLog를 출력했을 때 결과다.
2011-01-27 13:14:19.380 project[10058:207] <LoginView.m -[LoginView loginAction](49)> ^-^
다른 개발자들은 보통 어떻게 사용하고 있나 봤더니 다음과 같이 사용하는 개발자도 있었다. 참고해서 자기 스타일에 맞게 사용하자
/*
* There are three levels of logging: debug, info and error, and each can be enabled independently
* via the LOGGING_LEVEL_DEBUG, LOGGING_LEVEL_INFO, and LOGGING_LEVEL_ERROR switches below, respectively.
* In addition, ALL logging can be enabled or disabled via the LOGGING_ENABLED switch below.
*
* To perform logging, use any of the following function calls in your code:
*
* LogDebug(fmt, …) ? will print if LOGGING_LEVEL_DEBUG is set on.
* LogInfo(fmt, …) ? will print if LOGGING_LEVEL_INFO is set on.
* LogError(fmt, …) ? will print if LOGGING_LEVEL_ERROR is set on.
*
* Each logging entry can optionally automatically include class, method and line information by
* enabling the LOGGING_INCLUDE_CODE_LOCATION switch.
*
* Logging functions are implemented here via macros, so disabling logging, either entirely,
* or at a specific level, removes the corresponding log invocations from the compiled code,
* thus completely eliminating both the memory and CPU overhead that the logging calls would add.
*/
// Set this switch to enable or disable ALL logging.
#define LOGGING_ENABLED 1
// Set any or all of these switches to enable or disable logging at specific levels.
#define LOGGING_LEVEL_DEBUG 1
#define LOGGING_LEVEL_INFO 1
#define LOGGING_LEVEL_ERROR 1
// Set this switch to set whether or not to include class, method and line information in the log entries.
#define LOGGING_INCLUDE_CODE_LOCATION 1
// ***************** END OF USER SETTINGS ***************
#if !(defined(LOGGING_ENABLED) && LOGGING_ENABLED)
#undef LOGGING_LEVEL_DEBUG
#undef LOGGING_LEVEL_INFO
#undef LOGGING_LEVEL_ERROR
#endif
// Logging format
#define LOG_FORMAT_NO_LOCATION(fmt, lvl, …) NSLog((@”[%@] ” fmt), lvl, ##__VA_ARGS__)
#define LOG_FORMAT_WITH_LOCATION(fmt, lvl, …) NSLog((@”%s [Line %d] [%@] ” fmt), __PRETTY_FUNCTION__, __LINE__, lvl, ##__VA_ARGS__)
#if defined(LOGGING_INCLUDE_CODE_LOCATION) && LOGGING_INCLUDE_CODE_LOCATION
#define LOG_FORMAT(fmt, lvl, …) LOG_FORMAT_WITH_LOCATION(fmt, lvl, ##__VA_ARGS__)
#else
#define LOG_FORMAT(fmt, lvl, …) LOG_FORMAT_NO_LOCATION(fmt, lvl, ##__VA_ARGS__)
#endif
// Debug level logging
#if defined(LOGGING_LEVEL_DEBUG) && LOGGING_LEVEL_DEBUG
#define LogDebug(fmt, …) LOG_FORMAT(fmt, @”debug”, ##__VA_ARGS__)
#else
#define LogDebug(…)
#endif
// Info level logging
#if defined(LOGGING_LEVEL_INFO) && LOGGING_LEVEL_INFO
#define LogInfo(fmt, …) LOG_FORMAT(fmt, @”info”, ##__VA_ARGS__)
#else
#define LogInfo(…)
#endif
// Error level logging
#if defined(LOGGING_LEVEL_ERROR) && LOGGING_LEVEL_ERROR
#define LogError(fmt, …) LOG_FORMAT(fmt, @”***ERROR***”, ##__VA_ARGS__)
#else
#define LogError(…)
#endif
* There are three levels of logging: debug, info and error, and each can be enabled independently
* via the LOGGING_LEVEL_DEBUG, LOGGING_LEVEL_INFO, and LOGGING_LEVEL_ERROR switches below, respectively.
* In addition, ALL logging can be enabled or disabled via the LOGGING_ENABLED switch below.
*
* To perform logging, use any of the following function calls in your code:
*
* LogDebug(fmt, …) ? will print if LOGGING_LEVEL_DEBUG is set on.
* LogInfo(fmt, …) ? will print if LOGGING_LEVEL_INFO is set on.
* LogError(fmt, …) ? will print if LOGGING_LEVEL_ERROR is set on.
*
* Each logging entry can optionally automatically include class, method and line information by
* enabling the LOGGING_INCLUDE_CODE_LOCATION switch.
*
* Logging functions are implemented here via macros, so disabling logging, either entirely,
* or at a specific level, removes the corresponding log invocations from the compiled code,
* thus completely eliminating both the memory and CPU overhead that the logging calls would add.
*/
// Set this switch to enable or disable ALL logging.
#define LOGGING_ENABLED 1
// Set any or all of these switches to enable or disable logging at specific levels.
#define LOGGING_LEVEL_DEBUG 1
#define LOGGING_LEVEL_INFO 1
#define LOGGING_LEVEL_ERROR 1
// Set this switch to set whether or not to include class, method and line information in the log entries.
#define LOGGING_INCLUDE_CODE_LOCATION 1
// ***************** END OF USER SETTINGS ***************
#if !(defined(LOGGING_ENABLED) && LOGGING_ENABLED)
#undef LOGGING_LEVEL_DEBUG
#undef LOGGING_LEVEL_INFO
#undef LOGGING_LEVEL_ERROR
#endif
// Logging format
#define LOG_FORMAT_NO_LOCATION(fmt, lvl, …) NSLog((@”[%@] ” fmt), lvl, ##__VA_ARGS__)
#define LOG_FORMAT_WITH_LOCATION(fmt, lvl, …) NSLog((@”%s [Line %d] [%@] ” fmt), __PRETTY_FUNCTION__, __LINE__, lvl, ##__VA_ARGS__)
#if defined(LOGGING_INCLUDE_CODE_LOCATION) && LOGGING_INCLUDE_CODE_LOCATION
#define LOG_FORMAT(fmt, lvl, …) LOG_FORMAT_WITH_LOCATION(fmt, lvl, ##__VA_ARGS__)
#else
#define LOG_FORMAT(fmt, lvl, …) LOG_FORMAT_NO_LOCATION(fmt, lvl, ##__VA_ARGS__)
#endif
// Debug level logging
#if defined(LOGGING_LEVEL_DEBUG) && LOGGING_LEVEL_DEBUG
#define LogDebug(fmt, …) LOG_FORMAT(fmt, @”debug”, ##__VA_ARGS__)
#else
#define LogDebug(…)
#endif
// Info level logging
#if defined(LOGGING_LEVEL_INFO) && LOGGING_LEVEL_INFO
#define LogInfo(fmt, …) LOG_FORMAT(fmt, @”info”, ##__VA_ARGS__)
#else
#define LogInfo(…)
#endif
// Error level logging
#if defined(LOGGING_LEVEL_ERROR) && LOGGING_LEVEL_ERROR
#define LogError(fmt, …) LOG_FORMAT(fmt, @”***ERROR***”, ##__VA_ARGS__)
#else
#define LogError(…)
#endif
더 알고 싶다면 아래 사이트를 참고!
http://developer.apple.com/library/mac/#documentation/DeveloperTools/gcc-4.0.1/cpp/Standard-Predefined-Macros.html
http://www.cimgf.com/2010/05/02/my-current-prefix-pch-file/
http://iphoneincubator.com/blog/debugging/the-evolution-of-a-replacement-for-nslog
'프로그래밍 > iOS' 카테고리의 다른 글
SNS에서처럼 날짜를 현재부터 지난시간을 계산하여 문자열로 만들기 (64) | 2012.07.21 |
---|---|
iPhone App's 개발 시 GUI 재구성 쉽게 하는 법 (0) | 2012.07.20 |
NSLog 업그레이드 + Debug 모드에서만 로깅하기 (0) | 2012.07.17 |
Build Acrhive 시 icon관련 에러가 발생할때 (0) | 2012.07.11 |
아이팟 모드 만들기 - iPod Library 접근하기 (0) | 2012.07.10 |