10

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

  1. 当我使用模拟器或直接在真实设备上运行时,能够注销任何我想要的东西
  2. 当我使用 maven 构建我的应用程序时,它会确保它们NSLogs被剥离或禁用。

Maven 依赖于远程存储库中的内容来实际进行构建,因此如果有一种方法可以在远程存储库提交期间禁用此日志,那么它也是一个解决方案。

4

4 回答 4

2

使用这个宏它会自动关闭登录发布模式。只需将所有替换NSLogDLog并在将来DLog用于日志记录。例子 :DLog(@"Text : %@",sometext);

#ifdef DEBUG
#   define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
#   define DLog(...)
#endif
于 2013-11-13T07:59:33.650 回答
1

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

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

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

如果未定义 DEBUG,则预处理器将在整个应用程序代码中删除所有 NSLog 语句。如果 DEBUG 没有自动添加到您的构建设置中,您可以简单地添加 #define DEBUG 语句并在构建发布时将其注释掉。

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

我已经在我发布的一个应用程序中成功地使用了它,以摆脱 NSLog 进行发布。

于 2013-10-07T21:45:21.740 回答
1

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

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

#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];
}
于 2013-08-14T16:24:23.817 回答
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
于 2014-03-26T09:04:29.243 回答