Удаление журналов при выпуске приложения iOS

В настоящее время я создаю два приложения для моего проекта, один в выпуске, а другой - в отладке (единственное, что меняется, - это профили настройки, используемые для подписи и конечные точки). Из-за некоторых политик я не должен создавать файлы ipa локально. Поэтому я использую maven для создания этих двух версий (выпуска и отладки) на основе script. Из-за той же политики вывод должен быть полностью удален из приложения (NSLog, printf...). Я знаю макросы препроцессора, но я не хочу полагаться на них, поскольку кто-то (не зная) может изменить их и поставить под угрозу то, что я хочу достичь. Поэтому я хочу:

  • Уметь выходить из системы все, что я хочу, когда я использую мой симулятор, или когда я запускаю прямо на реальном устройстве.
  • Когда я использую maven для создания моих приложений, он убедится, что NSLogs лишены или отключены.

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

Ответ 1

Это интересный запрос, но возможно, если вы готовы принять немного служебных накладных функций для каждого журнала, который пропускается. Существует хорошая функция внутри Framework EtPanKit, которая проверяет, соответствуют ли файлы, которые пытаются вызвать функцию журнала, массиву предварительно определенных классов в вашем файле Info.plist. В дополнение к тому, чтобы быть отличным фильтром отладки, все, что вам нужно сделать в Release Time, - удалить все ключи из plist или указать другое в вашей сборке Release без значений, связанных с ключом 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];
}

Ответ 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

Ответ 3

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

Добавьте в свой заголовок префикса следующее:

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

Если DEBUG не определен, все инструкции NSLog будут удалены препроцессором на протяжении всего кода приложения. Если DEBUG не добавляется автоматически в ваши настройки сборки, вы можете просто добавить инструкцию #define DEBUG и прокомментировать ее, когда ваша сборка будет выпущена.

То же самое можно сделать и для операторов printf().

Я успешно использовал это приложение, которое я выпустил для избавления от NSLog для выпуска.

Ответ 4

Вы можете добавить полную систему журналов следующим образом:

#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