Нужно ли отключать NSLog перед выпуском приложения? - PullRequest
115 голосов
/ 08 января 2010

При выпуске приложения для iPhone, если я отключу NSLog();, оно будет работать лучше?

Ответы [ 12 ]

125 голосов
/ 08 января 2010

Один из способов сделать это - перейти в настройки сборки и в конфигурации отладки добавить значение к значению «Макросы препроцессора», например:

DEBUG_MODE=1

Убедитесь, что вы делаете это только для конфигурации отладки, а не для бета-версии или версии выпуска. Затем в общем заголовочном файле вы можете сделать что-то вроде:

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

Теперь вместо NSLog везде используйте DLog. При тестировании и отладке вы получите отладочные сообщения. Когда вы будете готовы выпустить бета-версию или финальную версию, все эти строки DLog автоматически станут пустыми и ничего не будет отправлено. Таким образом, не требуется ручная установка переменных или комментирование NSLogs. Выбор цели сборки позаботится об этом.

116 голосов
/ 26 января 2014

Обновление для Xcode 5 и iOS 7

примечание: для решения Xcode 7 / Swift 2.1 для удаления print () операторов в сборке выпуска найдите мой ответ здесь .

Да, вы должны удалить любой оператор NSLog в своем коде выпуска, так как он просто замедляет ваш код и не используется в версии выпуска. К счастью, в Xcode 5 (iOS 7) удивительно просто удалить все ваши операторы NSLog «автоматически» в сборках релиза. Так почему бы не сделать это.

Сначала сделайте 3 шага, затем объяснение

1) в вашем проекте XCode найдите файл 'yourProjectName-prefix.pch' (обычно вы найдете его в группе «файлы поддержки», где находится файл main.m

2) добавить эти 3 строки в конец файла .pch:

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

3) проверить разницу между вашей версией «отладка» и «выпуск». Один из способов сделать это - «изменить схему» -> «запустить имя приложения» -> на вкладке «информация» выбрать, используя раскрывающийся список между отладкой и выпуском. В версии релиза вы не увидите вывод NSLog в консоли отладки!

Как все это работает?

Прежде всего, нужно знать, что препроцессор относительно «тупой» и просто действует как «заменитель текста» перед вызовом компилятора. Он заменяет все, что вы '#define', на то, что следует за оператором #define.

#define NSLog(...);

(...) обозначает «что-нибудь» между скобками (). Помните также ; в конце. Это не является строго необходимым, так как компилятор оптимизирует это, но мне нравится помещать его туда, так как это более «правильно». После нашего #define появляется «ничто», поэтому препроцессор заменит его на «ничто» и просто отбросит всю строку, начиная с NSLog... до ;.

Определить операторы можно условно, используя #ifdef (если определено) или #ifndef (если не определено)

здесь мы пишем #ifndef DEBUG, что означает «если символ DEBUG не определен». #ifdef или #ifndef должны быть закрыты с #endif

Xcode 5 по умолчанию определяет символ 'DEBUG' для нас, когда режим de build равен 'DEBUG'. В «выпуске» это не определено. Вы можете проверить это в настройках своего проекта, вкладка «Настройки сборки» -> прокрутите вниз до раздела «Apple LLVM 5.0 - Предварительная обработка» -> макросы препроцессора. Вы увидите, что символ 'DEBUG' не определен для сборок релиза!

наконец, файл .pch автоматически создается XCode и автоматически включается в каждый исходный файл во время компиляции. Так что вы бы поместили целую вещь #define в каждый из ваших исходных файлов.

31 голосов
/ 19 июля 2013

Почти все вышеприведенные ответы предлагают решение, но не объясняют проблему. Я сделал поиск в Google, и нашел причину. Вот мой ответ:

Да, если вы закомментируете NSLog в своей версии, производительность улучшится. Потому что NSLog довольно медленный. Почему? NSLog сделает две вещи: 1) записывает сообщения журнала в Apple System Logging (ASL), 2) если приложение работает в xcode, оно также пишет в stderr.

Основная проблема заключается в первом. Чтобы обеспечить безопасность потока, каждый раз, когда вызывается NSLog, он открывает соединение со средством ASL , отправляет сообщение и закрывает соединение. Операция подключения очень дорогая. Другая причина в том, что NSLog тратит некоторое время, чтобы получить временную метку для регистрации.

Ссылка от здесь .

23 голосов
/ 11 января 2013

Мой личный фаворит - использовать переменный макрос.

#ifdef NDEBUG
    #define NSLog(...) /* suppress NSLog when in release mode */
#endif
18 голосов
/ 03 декабря 2013

В дополнение ко всем людям, которые мудро прокомментировали, что вообще не вызывать NSLog() в производстве, работает немного быстрее, добавлю, что:

Все эти NSLog() выходные строки виднылюбому, кто загружает ваше приложение из магазина и запускает его с устройством, подключенным к компьютеру Mac с Xcode (через окно «Органайзер»).

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

13 голосов
/ 27 декабря 2011

Project Default Setting

Внутри текущей настройки по умолчанию проекта в XCode, макрос NS_BLOCK_ASSERTIONS будет установлен в 1 в версии выпуска и DEBUG=1 в версии отладки.

Итак, я предпочитаю следующий метод.

// NS_BLOCK_ASSERTIONS is defined by default, as shown in the screenshot above.
// Or, you can define yourself Flags in the `Other C Flags` -> `Release`.
#ifndef NS_BLOCK_ASSERTIONS
    #define _DEBUG
#endif

#ifdef _DEBUG
// for debug mode 
#define DLog(fmt,...) NSLog(@"%s " fmt, __FUNCTION, ##__VA_ARGS__) 
... /// something extra
#else
// for release mode
#define DLog(fmt,...) /* throw it away */
... /// something extra
#endif
5 голосов
/ 09 октября 2013

Все хорошие ответы, однако вот еще один маленький трюк, который вы можете рассмотреть, в основном на этапах разработки / тестирования вашего приложения.

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

Трюк:

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

#define NSLog(...)

( ПРИМЕЧАНИЕ: сделайте НЕ поместите этот файл .h, только файл .m! )

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

если вы хотите включить его снова, вы всегда можете использовать

#undef NSLog

Например, вы можете просто запретить вызовы NSLog вокруг определенной группы методов, выполнив что-то вроде

#define NSLog(...)
-(void) myProblematicMethodThatSometimesNeedsDebugging {
    ...
}
#undef NSLog
5 голосов
/ 08 января 2010

Да, вы должны отключить его. Особенно, если вы пытаетесь максимизировать скорость вашего кода. NSLogging вещи влево и вправо загрязняют системный журнал, который другие разработчики могут пытаться пролистать, и это может оказать большое влияние на критичный по скорости код (внутри циклов и т. Д.). Я случайно однажды оставил некоторые сообщения журнала в рекурсивной функции и должен выпустить обновление с «30% увеличением скорости!» несколько недель спустя ...; -)

3 голосов
/ 17 января 2010

NSLog работает медленно и не должен использоваться для релизных сборок. Простой макрос, подобный приведенному ниже, отключит его вместе со всеми вашими утверждениями, которые также должны быть отключены. В менее распространенном случае, когда вам нужен NSLog в сборке релиза, просто вызовите его напрямую. Не забудьте добавить "-DNDEBUG" в ваши настройки сборки "другие флаги c".

#ifdef NDEBUG
#define MYLog(f, ...) 
#else
#define MYLog(f, ...) NSLog(f, ## __VA_ARGS__)
#endif
2 голосов
/ 25 сентября 2013

в файле pch запишите это перед # endif

#define NSLog() //
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...