Верно ли, что NS64 () не должен использовать производственный код?

Мне сказали это несколько раз на этом самом сайте, но я хотел убедиться, что это действительно так.

Я ожидал, что сможет посыпать вызовы функций NSLog во всем моем коде, и что Xcode / gcc автоматически отключит эти вызовы при построении сборки Release / Distribution.

Не следует ли мне это использовать? Если да, то какие альтернативы наиболее распространены между опытными программистами Objective-C?

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

#define DEBUG_MODE #ifdef DEBUG_MODE #define DebugLog( s, ... ) NSLog( @"<%p %@:(%d)> %@", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] ) #else #define DebugLog( s, ... ) #endif 

Мне было проще включить весь этот оператор в заголовок префикса, а не его собственный файл. Вы могли бы, если хотите, создать более сложную систему ведения журнала, связав DebugLog с обычными объектами Objective-C. Например, у вас может быть class ведения журнала, который записывает его в собственный файл журнала (или базу данных) и включает аргумент «приоритет», который вы можете установить во время выполнения, поэтому отладочные сообщения не отображаются в вашей версии выпуска, но сообщения об ошибках ( если вы это сделали, вы можете сделать DebugLog (), WarningLog () и т. д.).

О, и имейте в виду, что #define DEBUG_MODE может быть повторно использован в разных местах вашего приложения. Например, в моем приложении я использую его, чтобы отключить проверки ключа лицензии и разрешить запуск приложения, если оно до определенной даты. Это позволяет мне распределять ограниченную по времени, полностью функциональную бета-версию с минимальными усилиями с моей стороны.

Поместите эти 3 строки в конец файла -prefix.pch:

 #ifndef DEBUG #define NSLog(...) /* suppress NSLog when in release mode */ #endif 

Вам не нужно ничего определять в своем проекте, потому что DEBUG определяется в настройках сборки по умолчанию при создании вашего проекта.

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

Приложения, которые засоряют системный журнал, раздражают и воспринимаются как непрофессиональные.

Я не могу комментировать ответ Марка Charbonneau , поэтому я отправлю это как ответ.

В дополнение к добавлению макроса в ваш предварительно скомпилированный заголовок, вы можете использовать конфигурации Target build для управления определением (или отсутствием определения) DEBUG_MODE .

Если вы выберете активную конфигурацию « Отладка », будет определен DEBUG_MODE , и макрос будет расширен до полного определения NSLog .

При выборе активной конфигурации « Release » не будет определяться DEBUG_MODE и ваш NSLog ging не будет DEBUG_MODE из сборки релиза.

шаги:

  • objective> Получить информацию
  • Вкладка сборки
  • Найдите «Макросы препроцессора» (или GCC_PREPROCESSOR_DEFINITIONS )
  • Выберите «Конфигурация: отладка»
  • Изменить определение на этом уровне
  • Добавить DEBUG_MODE=1
  • Выберите «Конфигурация: выпуск»
  • подтвердить, что DEBUG_MODE не установлен в GCC_PREPROCESSOR_DEFINITIONS

если вы опустите символ «=» в определении, вы получите сообщение об ошибке из препроцессора

Кроме того, вставьте этот комментарий (показано ниже) над определением макроса, чтобы напомнить вам, откуда определяется DEBUG_MACRO 😉

 // Target > Get Info > Build > GCC_PREPROCESSOR_DEFINITIONS // Configuration = Release:  // = Debug: DEBUG_MODE=1 

EDIT: метод, опубликованный Марком Шарбоно , и привлеченный к моему вниманию sho , намного лучше, чем этот.

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


Чтобы добиться автоматического (и ожидаемого) поведения в Xcode:

В настройках проекта перейдите на вкладку «Создать» и выберите конфигурацию «Отладка». Найдите раздел «Макросы препроцессора» и добавьте макрос с именем DEBUG_MODE .

EDIT: см . Ответ Марка Charbonneau для правильного способа включения и отключения ведения журнала с DEBUG_MODE макроса DEBUG_MODE .

Я согласен с Мэтью. Нет ничего плохого в NSLog в производственном коде. Фактически, это может быть полезно пользователю. Тем не менее, если единственная причина, по которой вы используете NSLog, – это помочь отладке, тогда да, это должно быть удалено перед выпуском.

Кроме того, поскольку вы отметили это как вопрос с iPhone, NSLog берет ресурсы, и это то, что iPhone имеет мало. Если вы NSLogging что-нибудь на iPhone, это отнимает процессорное время от вашего приложения. Использовать его мудро.

Простая истина заключается в том, что NSLog просто медленный.

Но почему? Чтобы ответить на этот вопрос, давайте выясним, что делает NSLog, а затем как оно это делает.

Что делает NSLog точно?

NSLog делает 2 вещи:

Он записывает лог-сообщения в систему Apple Logging (asl). Это позволяет выводить сообщения журнала в Console.app. Он также проверяет, идет ли stream stderr приложения к терминалу (например, когда приложение запускается через Xcode). Если это так, он записывает сообщение журнала в stderr (чтобы он отображался в консоли Xcode).

Запись в STDERR затруднительна. Это может быть выполнено с помощью fprintf и ссылки на дескриптор файла stderr. Но как насчет ас?

Лучшая документация, которую я нашел о ASL, – это 10-страничное сообщение в блоге от Peter Hosey: link

Не вдаваясь в подробности, основной момент (поскольку это касается производительности) заключается в следующем:

Чтобы отправить сообщение журнала в средство ASL, вы в основном открываете клиентское соединение с деmonoм ASL и отправляете сообщение. НО – каждый stream должен использовать отдельное клиентское соединение. Таким образом, чтобы быть streamобезопасным, каждый раз, когда вызывается NSLog, он открывает новое клиентское соединение asl, отправляет сообщение и затем закрывает соединение.

Ресурсы можно найти здесь и здесь .

Как указано в других ответах, вы можете использовать #define для изменения использования NSLog или нет во время компиляции.

Однако более гибким способом является использование библиотеки журналов, таких как Cocoa Lumberjack, которая позволяет вам изменить, будет ли что-то регистрироваться во время выполнения.

В коде замените NSLog DDLogVerbose или DDLogError и т. Д., Добавьте #import для определений макросов и т. Д. И настройте регистраторы, часто в методе applicationDidFinishLaunching.

Чтобы иметь тот же эффект, что и NSLog, код конфигурации

 [DDLog addLogger:[DDASLLogger sharedInstance]]; [DDLog addLogger:[DDTTYLogger sharedInstance]]; 

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

С точки зрения аудита аудитор не хочет рассматривать каждое использование NSLog чтобы гарантировать его не регистрируемую конфиденциальную информацию. Он попросит вас удалить регистратор.

Я работаю с обеими группами. Мы проверяем код, записываем руководства по кодированию и т. Д. Наш гид требует, чтобы ведение журнала отключилось в производственном коде. Поэтому внутренние команды знают, что не пытаться это сделать;)

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

И помните, мы определяем «чувствительный», а не разработчик;)

Я также воспринимаю приложение, которое выполняет много протоколирования как приложение, готовое к взлому. Есть причина, по которой так много нужно выполнить каротаж, и обычно это не стабильность. Его прямо там с «сторожевыми» streamами, которые перезапускают висячие сервисы.

Если вы никогда не проходили обзор архитектуры безопасности (SecArch), это те вещи, на которые мы смотрим.

Вы не должны быть излишне подробными с printf или NSLog в коде выпуска. Попробуйте только делать printf или NSLog, если приложение имеет с ним что-то плохое, IE – неустранимая ошибка.

Имейте в виду, что NSLogs может замедлить работу пользовательского интерфейса / основного streamа. Лучше всего удалить их из релизов, если это абсолютно необходимо.

Я бы очень рекомендовал использовать TestFlight для регистрации (бесплатно). Их метод переопределит NSLog (используя макрос) и позволит вам включать / выключать ведение журнала на своем сервере, журнал системы Apple и журнал STDERR для всех ваших существующих вызовов в NSLog. Приятно отметить, что вы все равно можете просматривать сообщения журнала для приложений, развернутых в тестерах и приложениях, развернутых в App Store, без журналов, отображаемых в системном журнале пользователя. Лучшее из обоих миров.

  • TouchJSON, работающий с NSNull
  • Можно ли отделить основную функцию и classы C ++ от подпрограмм Objective-C и / или C при компиляции и ссылке?
  • Как я могу рассчитать разницу между двумя датами?
  • Код примера Objective-C для HMAC-SHA1
  • Запустить AppleScript из приложения Cocoa
  • Добавление объекта C ++ в Objective-C Class
  • В чем разница между «методом classа» и «статическим методом»?
  • Suppress warning "Категория реализует метод, который также будет реализован его основным classом"
  • objective-C: декларация о перекрестном classе
  • NSString tokenize в Objective-C
  • Как можно разрабатывать приложения для iPhone на Java?
  • Давайте будем гением компьютера.