Domanda

Currently I am building two apps for my project one in release & another in debug (the only thing that changes are provisioning profiles used to sign and the endpoints) . Because of some policies, I shouldn't be creating ipa files locally. So I use maven to build these two versions (release & debug), based on a script. Because of the same policies, output should be complete removed from the application (NSLog, printf...). I am aware of the preprocessor macros, but I don't want to rely on them, since someone (without knowing) might change them and jeopardise what I want to achieve. So what I want is:

  1. Be able to logout anything I want when I am using my simulator or when I run directly on a real device
  2. When I use maven to build my applications, it will make sure the NSLogs are stripped or disabled.

Maven relies on what's in a remote repository to actually make the build, so if there is a way of disabling this logs during the remote repo commit, it's a solution as well..

È stato utile?

Soluzione 2

It's an interesting request, but feasible if you're willing to accept a bit of function-call overhead for each log that gets skipped. There is a nice feature inside of the EtPanKit framework that checks if the files that are trying to call the log function match an array of pre-defined classes in your Info.plist file. In addition to being a great debug filter, all you'd have to do at Release time is remove all the keys from the plist or specify a different one in your Release build with no values associated with the LEPLogEnabledFilenames key.

In the interest of preventing link-rot, here's the function itself and the associated macros that make it a bit prettier to call:

#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];
}

Altri suggerimenti

Use this macro it will automatically off log on release mode. Just replace all NSLog with DLog and in future use DLog for logging. Example : DLog(@"Text : %@",sometext);

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

I understand you don't want to rely pre-processor macros, but there is a simple way to remove any NSLog statements using the pre-processor:

Add to your prefix header the following:

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

If DEBUG is not defined, then all NSLog statements will removed by the pre-processor throughout the app code. If DEBUG is not added automatically in your build settings, you can simply add a #define DEBUG statement and comment it out when your build for release.

The same can be done for printf() statements.

I've used this successfully in an app I've released for getting rid of NSLog for release.

You can add a complete log system like this:

#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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top