Me dijeron esto varias veces en este mismo sitio, pero quería asegurarme de que este sea realmente el caso.
Esperaba poder esparcir llamadas a la función NSLog en todo mi código, y que Xcode / gcc eliminaría automáticamente esas llamadas al compilar mis versiones de lanzamiento / distribución.
¿Debo evitar usar esto? Si es así, ¿qué alternativas son más comunes entre los programadores experimentados de Objective-C?
iphone
objective-c
nslog
jpm
fuente
fuente
Respuestas:
Las macros de preprocesador son realmente excelentes para la depuración. NSLog () no tiene nada de malo, pero es sencillo definir su propia función de registro con una mejor funcionalidad. Este es el que uso, incluye el nombre del archivo y el número de línea para que sea más fácil rastrear las declaraciones de registro.
Me resultó más fácil poner esta declaración completa en el encabezado del prefijo en lugar de su propio archivo. Si lo desea, puede crear un sistema de registro más complicado haciendo que DebugLog interactúe con los objetos normales de Objective-C. Por ejemplo, podría tener una clase de registro que escriba en su propio archivo de registro (o base de datos) e incluya un argumento de 'prioridad' que podría establecer en tiempo de ejecución, por lo que los mensajes de depuración no se muestran en su versión de lanzamiento, pero los mensajes de error son ( Si hiciera esto, podría crear DebugLog (), WarningLog (), etc.).
Ah, y tenga en cuenta que
#define DEBUG_MODE
puede reutilizarse en diferentes lugares de su aplicación. Por ejemplo, en mi aplicación lo uso para deshabilitar las comprobaciones de clave de licencia y solo permitir que la aplicación se ejecute si es anterior a una fecha determinada. Esto me permite distribuir una copia beta completamente funcional por tiempo limitado con un mínimo esfuerzo de mi parte.fuente
Coloque estas 3 líneas al final del archivo -prefix.pch:
No necesita definir nada en su proyecto, porque
DEBUG
se define en su configuración de compilación de forma predeterminada cuando crea su proyecto.fuente
Las llamadas de NSLog se pueden dejar en el código de producción, pero solo deben estar allí para casos realmente excepcionales, o la información que se desea que se registre en el registro del sistema.
Las aplicaciones que ensucian el registro del sistema son molestas y parecen poco profesionales.
fuente
No puedo comentar sobre la respuesta de Marc Charbonneau , así que publicaré esto como respuesta.
Además de agregar la macro a su encabezado precompilado, puede usar las configuraciones de compilación de Target para controlar la definición (o la falta de definición)
DEBUG_MODE
.Si selecciona la configuración activa " Depurar ",
DEBUG_MODE
se definirá y la macro se expandirá a laNSLog
definición completa .La selección de la configuración activa " Release " no definirá
DEBUG_MODE
y suNSLog
ging se omite de la versión de lanzamiento.Pasos:
GCC_PREPROCESSOR_DEFINITIONS
)DEBUG_MODE=1
DEBUG_MODE
no está configurado enGCC_PREPROCESSOR_DEFINITIONS
si omite el carácter '=' en la definición, recibirá un error del preprocesador
Además, pegue este comentario (que se muestra a continuación) sobre la definición de macro para recordarle de dónde
DEBUG_MACRO
viene la definición;)fuente
DEBUG_MODE
yDEBUG_MACRO
no son convencionales Solo encontré una referenciaDEBUG_MACRO
en el sitio de apple ( opensource.apple.com/source/gm4/gm4-15/src/m4.h?txt ). Quizás el más estándarDEBUG
yNDEBUG
sería mejores opciones?NDEBUG
es especificado por Posix; mientrasDEBUG
se usa por convención.EDIT: El método publicado por Marc Charbonneau , y trajo a mi atención por sho , es mucho mejor que éste.
He eliminado la parte de mi respuesta que sugería usar una función vacía para deshabilitar el registro cuando el modo de depuración está deshabilitado. La parte que se ocupa de establecer una macro de preprocesador automático sigue siendo relevante, por lo que permanece. También he editado el nombre de la macro del preprocesador para que encaje mejor con la respuesta de Marc Charbonneau.
Para lograr el comportamiento automático (y esperado) en Xcode:
En la configuración del proyecto, vaya a la pestaña "Compilar" y seleccione la configuración "Depurar". Busque la sección "Macros de preprocesador" y agregue una macro llamada
DEBUG_MODE
....
EDITAR: Vea la respuesta de Marc Charbonneau para conocer la forma correcta de habilitar y deshabilitar el registro con la
DEBUG_MODE
macro.fuente
Estoy de acuerdo con Matthew. No hay nada malo con NSLog en el código de producción. De hecho, puede ser útil para el usuario. Dicho esto, si la única razón por la que está usando NSLog es para ayudar a depurar, entonces, sí, eso debería eliminarse antes de liberarlo.
Además, dado que ha etiquetado esto como una pregunta de iPhone, NSLog toma recursos, que es algo de lo que el iPhone tiene muy poco. Si está registrando NSS cualquier cosa en el iPhone, eso le quita tiempo de procesador a su aplicación. Úsalo con sabiduría.
fuente
La simple verdad es que NSLog es simplemente lento.
¿Pero por qué? Para responder a esa pregunta, descubramos qué hace NSLog y cómo lo hace.
¿Qué hace exactamente NSLog?
NSLog hace 2 cosas:
Escribe mensajes de registro en la instalación de registro del sistema de Apple (ASL). Esto permite que los mensajes de registro aparezcan en Console.app. También verifica si el flujo stderr de la aplicación va a un terminal (como cuando la aplicación se ejecuta a través de Xcode). Si es así, escribe el mensaje de registro en stderr (para que aparezca en la consola Xcode).
Escribir a STDERR no suena difícil. Eso se puede lograr con fprintf y la referencia del descriptor de archivo stderr. ¿Pero qué hay de ASL?
La mejor documentación que he encontrado sobre ASL es una publicación de blog de 10 partes de Peter Hosey: enlace
Sin entrar en demasiados detalles, lo más destacado (en lo que respecta al rendimiento) es este:
Para enviar un mensaje de registro a la instalación de ASL, básicamente abre una conexión de cliente al demonio de ASL y envía el mensaje. PERO: cada subproceso debe usar una conexión de cliente separada. Por lo tanto, para ser seguro para subprocesos, cada vez que se llama NSLog, se abre una nueva conexión de cliente ASL, envía el mensaje y luego cierra la conexión.
Los recursos se pueden encontrar aquí y aquí .
fuente
Como se señaló en otras respuestas, puede usar un #define para modificar si NSLog se usa o no en el momento de la compilación.
Sin embargo, una forma más flexible es utilizar una biblioteca de registro como Cocoa Lumberjack que le permite cambiar si algo se registra también en tiempo de ejecución.
En su código, reemplace NSLog por DDLogVerbose o DDLogError, etc., agregue una #importación para las definiciones de macro, etc. y configure los registradores, a menudo en el método applicationDidFinishLaunching.
Para tener el mismo efecto que NSLog, el código de configuración es
fuente
Desde el punto de vista de la seguridad, depende de lo que se registre. Si
NSLog
(u otros registradores) está escribiendo información confidencial, entonces debe eliminar el registrador en el código de producción.Desde el punto de vista de la auditoría, el auditor no quiere examinar cada uso
NSLog
para asegurarse de que no está registrando información confidencial. Él / ella simplemente le dirá que quite el registrador.Yo trabajo con ambos grupos. Auditamos el código, escribimos las guías de codificación, etc. Nuestra guía requiere que el registro esté deshabilitado en el código de producción. Entonces los equipos internos saben que no deben intentarlo;)
También rechazaremos una aplicación externa que inicie sesión en producción porque no queremos aceptar el riesgo asociado con la filtración accidental de información confidencial. No nos importa lo que el desarrollador nos diga. Simplemente no vale la pena nuestro tiempo para investigar.
Y recuerde, definimos 'sensible', y no el desarrollador;)
También percibo una aplicación que realiza muchos registros como una aplicación lista para implosionar. Hay una razón por la que se realiza / necesita tanto registro, y generalmente no es estabilidad. Está a la altura de los hilos 'watchdog' que reinician los servicios bloqueados.
Si nunca ha pasado por una revisión de Arquitectura de seguridad (SecArch), este es el tipo de cosas que observamos.
fuente
No debe ser innecesariamente detallado con printf o NSLog en el código de lanzamiento. Intente solo hacer un printf o NSLog si la aplicación le sucede algo malo, es decir, un error irrecuperable.
fuente
Tenga en cuenta que NSLogs puede ralentizar la interfaz de usuario / subproceso principal. Es mejor eliminarlos de las versiones de lanzamiento a menos que sea absolutamente necesario.
fuente
Recomiendo usar TestFlight para iniciar sesión (gratis). Su método anulará NSLog (usando una macro) y le permitirá activar / desactivar el registro en su servidor, el registro del sistema Apple y el registro STDERR, para todas sus llamadas existentes a NSLog. Lo bueno de esto es que aún puede revisar sus mensajes de registro para las aplicaciones implementadas en los probadores y las aplicaciones implementadas en la App Store, sin que aparezcan los registros en el registro del sistema del usuario. Lo mejor de ambos mundos.
fuente