¿Necesito deshabilitar NSLog antes de lanzar la aplicación?


117

Al lanzar una aplicación para iPhone, si la desactivo, NSLog();¿funcionará mejor?


1
En mi proyecto actual utilizo UALogger . No inicia sesión en producción , si no lo solicita explícitamente. Y tiene otros beneficios sobre NSLog simple, como niveles de gravedad (con DEBUG , INFO , etc.) listos para usar . ¡Buen trabajo!
Anton Gaenko

1
Para responder a su pregunta sobre "¿funcionará mejor?" Sí, lo hace, pero el rendimiento que obtiene depende de cuántos NSLog()tenga en su aplicación. NSLog()lleva tiempo ejecutarse y agrega una sobrecarga adicional al tiempo de ejecución de su aplicación. De todos modos, si ayuda en el rendimiento con una simple macro de preprocesador DEBUG, entonces deberíamos deshabilitarlo.
Scott

También sugeriría que si tiene muchas declaraciones NSLog / print en su código, podría sugerirle que debería dedicar un tiempo a aprender más sobre el depurador. Regularmente establezco puntos de interrupción que imprimen la información que me interesa y continúan automáticamente. Sí, puede ralentizar un poco el funcionamiento, pero en la mayoría de los casos no es abrumador. Además, descansos condicionales para que pueda investigar cuándo sucedió algo inesperado.
bshirley

Respuestas:


127

Una forma de hacerlo es ir a la configuración de compilación y, en la configuración de depuración, agregar un valor al valor de "Macros de preprocesador" como:

DEBUG_MODE=1

Asegúrese de hacer esto solo para la configuración de depuración y no para las versiones Beta o Release. Luego, en un archivo de encabezado común, puede hacer algo como:

#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

Ahora en lugar de NSLog usarlo en DLogtodas partes. Al probar y depurar, obtendrá mensajes de depuración. Cuando esté listo para lanzar una versión beta o final, todas esas DLoglíneas se vacían automáticamente y no se emite nada. De esta manera, no hay configuración manual de variables ni comentarios NSLogsrequeridos. Elegir su objetivo de construcción se encarga de ello.


En Xcode 4.5 da una advertencia que dice: "La declaración implícita de la función 'DLog' no es válida en C99", así que esto no funciona.
Sergey Grischyov

2
@SergiusGee: Obtiene la advertencia de declaración implícita si no se puede encontrar la declaración de la función, en cuyo caso cree que está tratando de declararla. Asegúrese de que su clase tenga acceso al archivo de encabezado donde se declara.
sudo rm -rf

1
No eliminaré la sesión, ya que le roba la capacidad de recibir mejores informes de errores de los usuarios. use el registro asíncrono y logLevels para limitar el impacto de rendimiento a casi cero. (ver leñador de cacao o log4j de Java
Daij-Djan

2
Yo iría con #if en lugar de #ifdef, ya que DEBUG_MODE 0 seguirá por el camino verdadero
Grady Player

1
esto no responde la pregunta
Martin Mlostek

117

Actualización para Xcode 5 y iOS 7

nota: para que una solución Xcode 7 / Swift 2.1 elimine las declaraciones print () en una versión de lanzamiento, encuentre mi respuesta aquí .

Sí, debe eliminar cualquier declaración NSLog en su código de lanzamiento, ya que solo ralentiza su código y no es de ninguna utilidad en una versión de lanzamiento. Afortunadamente, en Xcode 5 (iOS 7), es increíblemente sencillo eliminar todas las declaraciones de NSLog 'automáticamente' en las versiones de lanzamiento. Entonces por qué no hacerlo.

Primero los 3 pasos a seguir, luego alguna explicación

1) en su proyecto Xcode, ubique el archivo 'yourProjectName-prefix.pch' (normalmente lo encontrará en el grupo 'archivos de soporte', donde se encuentra su archivo main.m

2) agregue estas 3 líneas al final del archivo '.pch':

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

3) pruebe la diferencia entre su versión de "depuración" y "lanzamiento". Una forma de hacer esto es a través de 'editar esquema' -> 'ejecutar nombre de la aplicación' -> debajo de la pestaña 'información', seleccione usando el cuadro desplegable entre depuración y liberación. En la versión de lanzamiento, no verá ningún resultado de NSLog en la consola de depuración.

¿Como funciona todo esto?

En primer lugar, uno debe saber que un preprocesador es relativamente 'tonto' y simplemente actúa como un 'reemplazador de texto' antes de que se llame al compilador. Reemplaza todo lo que '#defines' por lo que sigue a la #definedeclaración.

#define NSLog(...);

El (...)significa 'nada' entre los paréntesis (). Tenga en cuenta también ;el final. Esto no es estrictamente necesario ya que el compilador optimizará esto, pero me gusta ponerlo allí, ya que es más "correcto". Después de nuestro, #defineno hay 'nada', por lo que el preprocesador lo reemplazará con 'nada', por lo que simplemente descartará la línea completa, comenzando en NSLog...hasta e incluyendo el ;.

Definir declaraciones se pueden hacer condicional usando #ifdef(si está definido) o #ifndef(si no está definido)

aquí escribimos #ifndef DEBUG, que significa 'si el símbolo DEBUG no está definido'. El #ifdefo la #ifndefnecesidad de ser 'cerrado' con#endif

Xcode 5 define por defecto el símbolo 'DEBUG' para nosotros cuando el modo de construcción es 'DEBUG'. En 'lanzamiento' esto no está definido. puede verificar esto en la configuración de su proyecto, pestaña 'Configuración de compilación' -> desplácese hacia abajo hasta la sección 'Apple LLVM 5.0 - Preprocesamiento' -> macros de preprocesador. ¡Verá que el símbolo 'DEBUG' no está definido para versiones de lanzamiento!

finalmente, Xcode crea el archivo .pch automáticamente y se incluye automáticamente en cada archivo fuente durante el tiempo de compilación. Así que es como si lo hubiera puesto todo #defineen cada uno de sus archivos fuente.


1
Gracias @Whasssaaahhh, funciona muy bien. ¡Tenga cuidado de no poner código en declaraciones de registro! El preprocesador eliminará todas las NSLogdeclaraciones sin tener en cuenta lo que hay dentro.
Eric Platon

1
Si es un proyecto más antiguo que no tiene el indicador de depuración en las macros del preprocesador, es importante agregar "debug = 1" para el proyecto y no el objetivo
Priebe

1
Además, no lo use NSLogcomo una declaración de no hacer nada, por ejemplo, if(AllCool) NSLog(@"Cool!Do Nothing!"); else...NSLogif(AllCool) {NSLog(@"Cool!Do Nothing!");} else...
coloque

33

Casi todas las respuestas anteriores sugieren una solución pero no explican el problema. Hice una búsqueda en Google y encontré el motivo. Esta es mi respuesta:

Sí, si comenta NSLog en su versión de lanzamiento, el rendimiento mejorará. Porque NSLog es bastante lento.¿Por qué? NSLog hará dos cosas 1) escribir mensajes de registro en Apple System Logging (ASL), 2) si la aplicación se ejecuta en xcode, también escribirá en stderr.

El principal problema radica en el primero. Para lograr la seguridad de subprocesos, cada vez que se llama a NSLog, abre una conexión a la instalación de ASL , envía un mensaje y cierra la conexión. La operación de conexión es muy cara. Otra razón es que NSLog dedica algo de tiempo a registrar la marca de tiempo.

Referencia desde aquí .


23

Mi favorito personal es usar una macro variadic.

#ifdef NDEBUG
    #define NSLog(...) /* suppress NSLog when in release mode */
#endif

1
¿Dónde pones esto?
user6631314

20

Además de todas las personas que sabiamente comentaron que no llamar NSLog()en absoluto en producción funciona un poco más rápido, agregaré que:

Todas esas NSLog()cadenas de salida son visibles para cualquiera que descargue su aplicación de la tienda y la ejecute con el dispositivo conectado a una Mac que ejecute Xcode (a través de la ventana del Organizador).

Dependiendo de la información que registres (y especialmente si tu aplicación contacta con un servidor, realiza autenticación, etc.), esto puede ser un problema de seguridad serio .


gracias por la información, ¿está esto en el documento en alguna parte o simplemente lo descubrió usted mismo? ¿Sigue siendo válido para la impresión en Swift?
Ronny Webers

No recuerdo haber leído ninguna documentación. Acabo de instalar mi compilación archivada (el mismo binario que envié a la tienda) en mi dispositivo y lo conecté a Xcode. No tengo idea de si es lo mismo para Swift print(), pero lo más probable es que lo sea.
Nicolas Miari

@NicolasMiari ¿A qué te refieres con conectado a Xcode? Cómo podemos conectar nuestro binario en Xcode, en realidad quiero intentar lo mismo. Así que sugiérelo. Gracias.
iDevAmit

@iDeveloper Me refiero a descargar su aplicación desde la AppStore a un dispositivo (por ejemplo, un iPhone), conectar ese dispositivo a Xcode a través de USB, iniciar su aplicación y ver los registros en la ventana "Dispositivos" de Xcode.
Nicolas Miari

3
@Whasssaaahhh no se imprime en la consola del dispositivo ... acabo de probar eso
Anish Parajuli 웃

13

Configuración predeterminada del proyecto

Dentro de la configuración predeterminada actual del proyecto en Xcode, la NS_BLOCK_ASSERTIONSmacro se establecerá en 1 en la versión de lanzamiento, yDEBUG=1 en la versión de depuración.

Entonces, prefiero el siguiente método.

// 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

Sí, debería desactivarlo. Especialmente si está tratando de maximizar la velocidad de su código. NSLogging cosas a la izquierda y a la derecha contamina el registro del sistema que otros desarrolladores podrían estar tratando de explorar y puede tener un gran impacto en el código de velocidad crítica (bucles internos, etc.). Dejé accidentalmente algunos mensajes de registro en una función recursiva una vez y consiguió lanzar una actualización con un "30% de aumento de velocidad!" Unas pocas semanas después... ;-)


5

Todas son buenas respuestas, sin embargo, aquí hay otro pequeño truco que puede considerar usar, principalmente en las fases de desarrollo / prueba de su aplicación.

También podría ser útil para el código de lanzamiento de la aplicación, si solo desea desactivar SU código de depuración, y no mensajes que puedan indicar problemas fuera del control directo de su código.

El truco:

Puede desactivar NSLog por archivo .m simplemente incluyendo la siguiente línea en la parte superior del archivo .m :

#define NSLog(...)

( NOTA: NO coloque este archivo .h, ¡solo el archivo .m! )

Esto solo hace que el compilador evalúe NSLog() expandiendo su macro de preprocesador en su lugar. La macro no hace más que eliminar los argumentos.

si desea volver a encenderlo, siempre puede usar

#undef NSLog

Por ejemplo, podría evitar las llamadas a NSLog alrededor de un grupo particular de métodos haciendo algo como

#define NSLog(...)
-(void) myProblematicMethodThatSometimesNeedsDebugging {
    ...
}
#undef NSLog

3

NSLog es lento y no debe usarse para versiones de lanzamiento. Una macro simple como la que se muestra a continuación la desactivará junto con cualquier afirmación que pueda tener y que también debería estar desactivada. En el caso menos común en el que desea NSLog en una versión de lanzamiento, simplemente llámelo directamente. No olvide agregar "-DNDEBUG" a la configuración de compilación de "otros indicadores de c".

#ifdef NDEBUG
#define MYLog(f, ...) 
#else
#define MYLog(f, ...) NSLog(f, ## __VA_ARGS__)
#endif


0

que hay de esto

#ifndef DEBUG_MODE
        fclose(stderr);     // the simplest way to disable output from NSLog
#endif    

1
esto deshabilita la salida, pero no ahorra tiempo de procesamiento, es decir, NSLog todavía se llama y sus argumentos se
analizan

0
var showDebugLogs = false;

    func DLog(format: String, args: CVarArgType...) {
        if showDebugLogs{
        println(String(format: format, arguments: args))
        }
    }

Esto también aceptará los argumentos adicionales. Solo el valor del parámetro showDebugLogs en verdadero o falso, según su necesidad


Esto es bueno, pero todavía tiene el problema de toda la sobrecarga de llamadas y de cualquier sobrecarga (y posibles efectos secundarios) de calcular los argumentos pasados ​​a la Dlogfunción.
Todd Lehman
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.