在发布iOS应用程序时删除日志

时间:2013-08-14 12:49:42

标签: ios maven nslog

目前,我正在为我的项目构建两个应用程序,一个是发行版和版本。另一个在调试中(唯一改变的是用于签名和端点的配置文件)。由于某些策略,我不应该在本地创建ipa文件。所以我使用maven来构建这两个版本(发布和调试),基于脚本。由于相同的策略,应该从应用程序(NSLog,printf ...)中完全删除输出。 我知道预处理器宏,但我不想依赖它们,因为某人(不知道)可能会改变它们并危及我想要实现的目标。所以我想要的是:

  1. 当我使用我的模拟器或直接在真实设备上运行时,能够注销我想要的任何东西
  2. 当我使用maven构建我的应用程序时,它将确保NSLogs被剥离或禁用。
  3. Maven依赖远程存储库中的内容实际进行构建,因此如果有一种方法可以在远程repo提交期间禁用此日志,那么它也是一个解决方案..

4 个答案:

答案 0 :(得分:2)

使用此宏,它将自动关闭登录发布模式。 只需将所有NSLog替换为DLog,并在将来使用DLog进行日志记录。 示例:DLog(@"Text : %@",sometext);

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

答案 1 :(得分:1)

这是一个有趣的请求,但如果您愿意为每个被跳过的日志接受一些函数调用开销,那么这是可行的。 EtPanKit framework内部有一个很好的功能,用于检查尝试调用日志函数的文件是否与Info.plist文件中的预定义类数组匹配。除了是一个出色的调试过滤器之外,您在发布时需要做的就是从plist中删除所有键,或者在Release版本中指定一个不同的键,而不使用与LEPLogEnabledFilenames键相关联的值。 / p>

为了防止链接腐烂,这里是函数本身和相关的宏,使它调用更漂亮:

#define LEPLogStack(...) LEPLogInternal(__FILE__, __LINE__, 1, __VA_ARGS__)
#define LEPLog(...) LEPLogInternal(__FILE__, __LINE__, 0, __VA_ARGS__)

#import <Foundation/Foundation.h>
#import <libgen.h>
#import <time.h>
#import <sys/time.h>
#include <execinfo.h>
#include <pthread.h>

static NSSet * enabledFilesSet = nil;
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

void LEPLogInternal(const char * filename, unsigned int line, int dumpStack, NSString * format, ...)
{
    va_list argp;
    NSString * str;
    NSAutoreleasePool * pool;
    char * filenameCopy;
    char * lastPathComponent;
    struct timeval tv;
    struct tm tm_value;
    //NSDictionary * enabledFilenames;

    pool = [[NSAutoreleasePool alloc] init];

    pthread_mutex_lock(&lock);
    if (enabledFilesSet == nil) {
        enabledFilesSet = [[NSSet alloc] initWithArray:[[NSUserDefaults standardUserDefaults] arrayForKey:LEPLogEnabledFilenames]];
    }
    pthread_mutex_unlock(&lock);

    NSString * fn;
    fn = [[NSFileManager defaultManager] stringWithFileSystemRepresentation:filename length:strlen(filename)];
    fn = [fn lastPathComponent];
    if (![enabledFilesSet containsObject:fn]) {
        [pool release];
        return;
    }

    va_start(argp, format);
    str = [[NSString alloc] initWithFormat:format arguments:argp];
    va_end(argp);

    NSString * outputFileName = [[NSUserDefaults standardUserDefaults] stringForKey:LEPLogOutputFilename];
    static FILE * outputfileStream = NULL;
    if ( ( NULL == outputfileStream ) && outputFileName )
    {
        outputfileStream = fopen( [outputFileName UTF8String], "w+" );
    }

    if ( NULL == outputfileStream )
        outputfileStream = stderr;

    gettimeofday(&tv, NULL);
    localtime_r(&tv.tv_sec, &tm_value);
    fprintf(outputfileStream, "%04u-%02u-%02u %02u:%02u:%02u.%03u ", tm_value.tm_year + 1900, tm_value.tm_mon + 1, tm_value.tm_mday, tm_value.tm_hour, tm_value.tm_min, tm_value.tm_sec, tv.tv_usec / 1000);
    //fprintf(stderr, "%10s ", [[[NSDate date] description] UTF8String]);
    fprintf(outputfileStream, "[%s:%u] ", [[[NSProcessInfo processInfo] processName] UTF8String], [[NSProcessInfo processInfo] processIdentifier]);
    filenameCopy = strdup(filename);
    lastPathComponent = basename(filenameCopy);
    fprintf(outputfileStream, "(%s:%u) ", lastPathComponent, line);
    free(filenameCopy);
    fprintf(outputfileStream, "%s\n", [str UTF8String]);
    [str release];

    if (dumpStack) {
        void * frame[128];
        int frameCount;
        int i;

        frameCount = backtrace(frame, 128);
        for(i = 0 ; i < frameCount ; i ++) {
            fprintf(outputfileStream, "  %p\n", frame[i]);
        }
    }

    if ( outputFileName )
    {
        fflush(outputfileStream);
    }

    [pool release];
}

答案 2 :(得分:1)

我知道您不想依赖预处理器宏,但有一种简单的方法可以使用预处理器删除任何NSLog语句:

在您的前缀标题中添加以下内容:

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

如果未定义DEBUG,则预处理器将在整个应用程序代码中删除所有NSLog语句。 如果未在构建设置中自动添加DEBUG,则只需添加#define DEBUG语句,并在构建版本时将其注释掉。

对printf()语句也可以这样做。

我已经在我发布的应用程序中成功使用了它,以便摆脱NSLog的发布。

答案 3 :(得分:0)

您可以添加如下完整的日志系统:

#ifndef Logs_h
#define Logs_h

    /* Log levels */
    #define LOG_LEVEL_NO_LOG 0
    #define LOG_LEVEL_ONLY_ERRORS 1
    #define LOG_LEVEL_ERROS_AND_WARNINGS 2
    #define LOG_LEVEL_LOG_ALL 3
    /* Log levels */


    #ifdef DEBUG
        #define LOG_LEVEL LOG_LEVEL_LOG_ALL /* <-- Change The Log Level here */
    #else
        #define LOG_LEVEL LOG_LEVEL_NO_LOG /* No logs on release now */
    #endif


    /* Logs Macros */

    #if LOG_LEVEL >= LOG_LEVEL_LOG_ALL
        #define DebugLog(fmt, ...) NSLog(@"[Debug] %s [Line %d]: " fmt, __PRETTY_FUNCTION__, __LINE__, ## __VA_ARGS__)
    #else
        #define DebugLog(...) /* */
    #endif

    #if LOG_LEVEL >= LOG_LEVEL_ERROS_AND_WARNINGS
        #define WarnLog(fmt, ...) NSLog(@"[Warning] %s [Line %d]: " fmt, __PRETTY_FUNCTION__, __LINE__, ## __VA_ARGS__)
    #else
        #define WarnLog(...) /* */
    #endif

    #if LOG_LEVEL >= LOG_LEVEL_ONLY_ERRORS
        #define ErrorLog(fmt, ...) NSLog(@"[Error] %s [Line %d]: " fmt, __PRETTY_FUNCTION__, __LINE__, ## __VA_ARGS__)
    #else
        #define ErrorLog(...) /* */
    #endif

#endif