Мне говорили об этом несколько раз на этом самом сайте, но я хотел убедиться, что это действительно так.
Я ожидал, что смогу распределить вызовы функций NSLog по всему коду, и что Xcode / gcc автоматически удалит эти вызовы при сборке моих сборок Release / Distribution.
Должен ли я избегать использования этого? Если да, то какие альтернативы наиболее распространены среди опытных программистов Objective-C?
Ответы:
Макросы препроцессора действительно хороши для отладки. В NSLog () нет ничего плохого, но просто определить собственную функцию ведения журнала с лучшей функциональностью. Вот тот, который я использую, он включает имя файла и номер строки, чтобы упростить отслеживание операторов журнала.
Мне было проще поместить весь этот оператор в заголовок префикса, а не в его собственный файл. При желании вы можете создать более сложную систему ведения журнала, взаимодействуя с DebugLog с обычными объектами Objective-C. Например, у вас может быть класс ведения журнала, который записывает в свой собственный файл журнала (или базу данных) и включает в себя аргумент «приоритет», который вы можете установить во время выполнения, чтобы отладочные сообщения не отображались в вашей версии выпуска, а сообщения об ошибках ( если вы сделали это, вы можете сделать DebugLog (), WarningLog () и так далее).
Да, и имейте в виду,
#define DEBUG_MODE
можно повторно использовать в разных местах в вашем приложении. Например, в моем приложении я использую его, чтобы отключить проверку лицензионного ключа и разрешить запуск приложения только в том случае, если это происходит до определенной даты. Это позволяет мне распространять ограниченную по времени полнофункциональную бета-копию с минимальными усилиями с моей стороны.источник
Поместите эти 3 строки в конец файла -prefix.pch:
Вам не нужно ничего определять в вашем проекте, потому что
DEBUG
он определяется в настройках сборки по умолчанию при создании проекта.источник
Вызовы NSLog могут быть оставлены в производственном коде, но должны быть там только для действительно исключительных случаев или информации, которая требуется, которая будет записана в системный журнал.
Приложения, которые засоряют системный журнал, раздражают и кажутся непрофессиональными.
источник
Я не могу комментировать ответ Марка Шарбонно , поэтому я опубликую это как ответ.
Помимо добавления макроса в предварительно скомпилированный заголовок, вы можете использовать конфигурации сборки Target для управления определением (или отсутствием определения)
DEBUG_MODE
.Если вы выберете « Отладка », активная конфигурация
DEBUG_MODE
будет определена, и макрос развернется до полногоNSLog
определения.Выбор активной конфигурации « Release » не определит,
DEBUG_MODE
и вашNSLog
ging будет опущен в сборке релиза.шаги:
GCC_PREPROCESSOR_DEFINITIONS
)DEBUG_MODE=1
DEBUG_MODE
не установлено вGCC_PREPROCESSOR_DEFINITIONS
если вы опустите символ '=' в определении, вы получите ошибку от препроцессора
Кроме того, вставьте этот комментарий (показанный ниже) над определением макроса, чтобы напомнить вам, откуда это
DEBUG_MACRO
определение;)источник
DEBUG_MODE
иDEBUG_MACRO
нетрадиционны. Я нашел только одну ссылкуDEBUG_MACRO
на сайте Apple ( opensource.apple.com/source/gm4/gm4-15/src/m4.h?txt ). Возможно, более стандартныйDEBUG
иNDEBUG
будет лучший выбор?NDEBUG
указан Posix; покаDEBUG
используется по соглашению.EDIT: метод отправленный Марком Шарбонно , и обратил мое внимание на шо , гораздо лучше , чем этот.
Я удалил часть своего ответа, в которой предлагалось использовать пустую функцию, чтобы отключить ведение журнала при отключенном режиме отладки. Часть, которая имеет дело с установкой автоматического макроса препроцессора, все еще актуальна, поэтому она остается. Я также отредактировал название макроса препроцессора, чтобы он лучше подходил к ответу Марка Шарбонно.
Чтобы достигнуть автоматического (и ожидаемого) поведения в XCode:
В настройках проекта перейдите на вкладку «Сборка» и выберите конфигурацию «Отладка». Найдите раздел «Макросы препроцессора» и добавьте макрос с именем
DEBUG_MODE
....
РЕДАКТИРОВАТЬ: См . Ответ Марка Charbonneau для правильного включения и отключения ведения журнала с помощью
DEBUG_MODE
макроса.источник
Я согласен с Мэтью. Нет ничего плохого в NSLog в рабочем коде. На самом деле, это может быть полезно для пользователя. Тем не менее, если единственная причина, по которой вы используете NSLog, состоит в том, чтобы помочь отладке, тогда, да, это следует удалить перед выпуском.
Кроме того, поскольку вы отметили это как вопрос об iPhone, NSLog забирает ресурсы, а это то, чего у iPhone очень мало. Если вы NSLogging что-то на iPhone, это отнимает процессорное время из вашего приложения. Использовать его мудро.
источник
Простая правда в том, что NSLog просто медленный.
Но почему? Чтобы ответить на этот вопрос, давайте выясним, что делает NSLog, а затем, как он это делает.
Что именно делает NSLog?
NSLog делает 2 вещи:
Он записывает сообщения журнала в систему Apple System Logging (asl). Это позволяет журнальным сообщениям отображаться в Console.app. Он также проверяет, идет ли поток приложения stderr на терминал (например, когда приложение запускается через XCode). Если это так, он записывает сообщение журнала в stderr (чтобы оно отображалось в консоли Xcode).
Запись в STDERR не кажется сложной. Это можно сделать с помощью fprintf и ссылки на дескриптор файла stderr. Но как насчет Асл?
Лучшая документация, которую я нашел об ASL, - это блог из Питера Хоси, состоящий из 10 частей: ссылка
Не вдаваясь в подробности, основной момент (в том, что касается производительности) заключается в следующем:
Чтобы отправить сообщение журнала в средство ASL, вы в основном открываете клиентское соединение с демоном ASL и отправляете сообщение. НО - каждый поток должен использовать отдельное клиентское соединение. Поэтому для обеспечения безопасности потоков каждый раз, когда вызывается NSLog, он открывает новое клиентское соединение asl, отправляет сообщение, а затем закрывает соединение.
Ресурсы можно найти здесь и здесь .
источник
Как отмечалось в других ответах, вы можете использовать #define, чтобы изменить, используется ли NSLog или нет во время компиляции.
Однако более гибкий способ - использовать библиотеку журналов, такую как Cocoa Lumberjack, которая позволяет вам изменять, регистрируется ли что-либо также во время выполнения.
В вашем коде замените NSLog на DDLogVerbose или DDLogError и т. Д., Добавьте #import для определений макросов и т. Д. И настройте регистраторы, часто в методе applicationDidFinishLaunching.
Чтобы иметь тот же эффект, что и NSLog, код конфигурации
источник
С точки зрения безопасности, это зависит от того, что регистрируется. Если
NSLog
(или другие регистраторы) записывают конфиденциальную информацию, то вы должны удалить регистратор в рабочем коде.С аудиторской точки зрения, аудитор не хочет рассматривать каждое использование
NSLog
чтобы гарантировать, что он не регистрирует конфиденциальную информацию. Он / она просто скажет вам удалить регистратор.Я работаю с обеими группами. Мы проводим аудит кода, пишем руководства по кодированию и т. Д. Наше руководство требует, чтобы ведение журнала было отключено в рабочем коде. Так что внутренние команды знают, что не стоит пробовать;)
Мы также отклоним внешнее приложение, которое входит в систему, потому что мы не хотим принимать на себя риск, связанный со случайной утечкой конфиденциальной информации. Нам все равно, что говорит нам разработчик. Это просто не стоит нашего времени, чтобы исследовать.
И помните, мы определяем «чувствительный», а не разработчик;)
Я также воспринимаю приложение, которое выполняет много журналов, как приложение, готовое взорваться. Есть причина, по которой так много журналирования выполняется / необходимо, и это обычно не стабильность. Это прямо там с «сторожевыми» потоками, которые перезапускают зависшие сервисы.
Если вы никогда не проходили обзор архитектуры безопасности (SecArch), мы рассмотрим именно такие вещи.
источник
Вы не должны быть слишком многословны с printf или NSLog в коде выпуска. Попробуйте выполнять только printf или NSLog, если с приложением случится что-то плохое, то есть IE - неисправимая ошибка.
источник
Имейте в виду, что NSLogs может замедлить UI / основной поток. Лучше удалить их из релизных сборок, если в этом нет крайней необходимости.
источник
Я настоятельно рекомендую использовать TestFlight для регистрации (бесплатно). Их метод переопределит NSLog (с помощью макроса) и позволит вам включить / выключить ведение журнала на их сервер, журнал системы Apple и журнал STDERR для всех ваших существующих вызовов NSLog. Приятно то, что вы по-прежнему можете просматривать сообщения журнала для приложений, развернутых в тестерах, и приложений, развернутых в App Store, и журналы не отображаются в системном журнале пользователя. Лучший из двух миров.
источник