Как распечатать название метода и номер строки и условно отключить NSLog? - PullRequest
444 голосов
/ 09 июня 2009

Я делаю презентацию по отладке в Xcode и хотел бы получить больше информации об эффективном использовании NSLog.

В частности, у меня есть два вопроса:

  • Есть ли способ легко NSLog имя текущего метода / номер строки?
  • есть ли способ легко "отключить" все NSLogs перед компиляцией кода выпуска?

Ответы [ 13 ]

5 голосов
/ 09 января 2013

построение поверх приведенных выше ответов, вот что я плагиат и придумал. Также добавлено ведение журнала памяти.

#import <mach/mach.h>

#ifdef DEBUG
#   define DebugLog(fmt, ...) NSLog((@"%s(%d) " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
#   define DebugLog(...)
#endif


#define AlwaysLog(fmt, ...) NSLog((@"%s(%d) " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);


#ifdef DEBUG
#   define AlertLog(fmt, ...)  { \
    UIAlertView *alert = [[UIAlertView alloc] \
            initWithTitle : [NSString stringWithFormat:@"%s(Line: %d) ", __PRETTY_FUNCTION__, __LINE__]\
                  message : [NSString stringWithFormat : fmt, ##__VA_ARGS__]\
                 delegate : nil\
        cancelButtonTitle : @"Ok"\
        otherButtonTitles : nil];\
    [alert show];\
}
#else
#   define AlertLog(...)
#endif



#ifdef DEBUG
#   define DPFLog NSLog(@"%s(%d)", __PRETTY_FUNCTION__, __LINE__);//Debug Pretty Function Log
#else
#   define DPFLog
#endif


#ifdef DEBUG
#   define MemoryLog {\
    struct task_basic_info info;\
    mach_msg_type_number_t size = sizeof(info);\
    kern_return_t e = task_info(mach_task_self(),\
                                   TASK_BASIC_INFO,\
                                   (task_info_t)&info,\
                                   &size);\
    if(KERN_SUCCESS == e) {\
        NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; \
        [formatter setNumberStyle:NSNumberFormatterDecimalStyle]; \
        DebugLog(@"%@ bytes", [formatter stringFromNumber:[NSNumber numberWithInteger:info.resident_size]]);\
    } else {\
        DebugLog(@"Error with task_info(): %s", mach_error_string(e));\
    }\
}
#else
#   define MemoryLog
#endif
4 голосов
/ 07 сентября 2011

Новое дополнение к DLog. Вместо полного удаления отладки из выпущенного приложения, только отключите его. Когда у пользователя возникают проблемы, требующие отладки, просто скажите, как включить отладку в выпущенном приложении и запросить данные журнала по электронной почте.

Короткая версия: создайте глобальную переменную (да, ленивое и простое решение) и измените DLog следующим образом:

BOOL myDebugEnabled = FALSE;
#define DLog(fmt, ...) if (myDebugEnabled) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);

Более длинный ответ на Jomnius iLessons iLearned: Как вести журнал динамической отладки в выпущенном приложении

3 голосов
/ 12 февраля 2014

В течение некоторого времени я использовал сайт макросов, взятых из нескольких выше. Мое внимание сосредоточено на регистрации в Консоли, с акцентом на контролируемое и отфильтрованное многословие ; если вы не возражаете против большого количества строк журнала, но хотите легко включать и выключать их, тогда это может оказаться полезным.

Во-первых, я необязательно заменяю NSLog на printf, как описано @Rodrigo выше

#define NSLOG_DROPCHAFF//comment out to get usual date/time ,etc:2011-11-03 13:43:55.632 myApp[3739:207] Hello Word

#ifdef NSLOG_DROPCHAFF
#define NSLog(FORMAT, ...) printf("%s\n", [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
#endif

Далее я включаю или выключаю регистрацию.

#ifdef DEBUG
#define LOG_CATEGORY_DETAIL// comment out to turn all conditional logging off while keeping other DEBUG features
#endif

В главном блоке определите различные категории , соответствующие модулям в вашем приложении. Также определите протоколирование level , выше которого журналирование вызовов не будет вызываться. Затем определите различные ароматы вывода NSLog

#ifdef LOG_CATEGORY_DETAIL

    //define the categories using bitwise leftshift operators
    #define kLogGCD (1<<0)
    #define kLogCoreCreate (1<<1)
    #define kLogModel (1<<2)
    #define kLogVC (1<<3)
    #define kLogFile (1<<4)
    //etc

    //add the categories that should be logged...
    #define kLOGIFcategory kLogModel+kLogVC+kLogCoreCreate

    //...and the maximum detailLevel to report (use -1 to override the category switch)
    #define kLOGIFdetailLTEQ 4

    // output looks like this:"-[AppDelegate myMethod] log string..."
    #   define myLog(category,detailLevel,format, ...) if(detailLevel<0 || ((category&kLOGIFcategory)&&detailLevel<= kLOGIFdetailLTEQ)) {NSLog((@"%s " format), __PRETTY_FUNCTION__, ##__VA_ARGS__);}

    // output also shows line number:"-[AppDelegate myMethod][l17]  log string..."
    #   define myLogLine(category,detailLevel,format, ...) if(detailLevel<0 || ((category&kLOGIFcategory)&&detailLevel<= kLOGIFdetailLTEQ)) {NSLog((@"%s[l%i] " format), __PRETTY_FUNCTION__,__LINE__ ,##__VA_ARGS__);}

    // output very simple:" log string..."
    #   define myLogSimple(category,detailLevel,format, ...) if(detailLevel<0 || ((category&kLOGIFcategory)&&detailLevel<= kLOGIFdetailLTEQ)) {NSLog((@"" format), ##__VA_ARGS__);}

    //as myLog but only shows method name: "myMethod: log string..."
    // (Doesn't work in C-functions)
    #   define myLog_cmd(category,detailLevel,format,...) if(detailLevel<0 || ((category&kLOGIFcategory)&&detailLevel<= kLOGIFdetailLTEQ)) {NSLog((@"%@: " format), NSStringFromSelector(_cmd), ##__VA_ARGS__);}

    //as myLogLine but only shows method name: "myMethod>l17: log string..."
    #   define myLog_cmdLine(category,detailLevel,format, ...) if(detailLevel<0 || ((category&kLOGIFcategory)&&detailLevel<= kLOGIFdetailLTEQ)) {NSLog((@"%@>l%i: " format), NSStringFromSelector(_cmd),__LINE__ , ##__VA_ARGS__);}

    //or define your own...
   // # define myLogEAGLcontext(category,detailLevel,format, ...) if(detailLevel<0 || ((category&kLOGIFcategory)&&detailLevel<= kLOGIFdetailLTEQ)) {NSLog((@"%s>l%i (ctx:%@)" format), __PRETTY_FUNCTION__,__LINE__ ,[EAGLContext currentContext], ##__VA_ARGS__);}

#else
    #   define myLog_cmd(...)
    #   define myLog_cmdLine(...)
    #   define myLog(...)
    #   define myLogLine(...)
    #   define myLogSimple(...)
    //#   define myLogEAGLcontext(...)
#endif

Таким образом, с текущими настройками для kLOGIFcategory и kLOGIFdetailLTEQ, вызов типа

myLogLine(kLogVC, 2, @"%@",self);

будет печатать, но это не будет

myLogLine(kLogGCD, 2, @"%@",self);//GCD not being printed

и не будет

myLogLine(kLogGCD, 12, @"%@",self);//level too high

Если вы хотите переопределить настройки для отдельного журнала вызовов, используйте отрицательный уровень:

myLogLine(kLogGCD, -2, @"%@",self);//now printed even tho' GCD category not active.

Я считаю, что несколько дополнительных символов ввода каждой строки стоят того, что я могу

  1. Включение или отключение всей категории комментариев (например, сообщать только о тех вызовах, помеченных как Модель)
  2. отчет о мелких деталях с номерами более высокого уровня или только о наиболее важных вызовах, отмеченных номерами более низкого уровня

Я уверен, что многие найдут это немного излишним, но на тот случай, если кто-то найдет, что это соответствует их целям.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...