Consejo rápido Personalice NSLog para una depuración más fácil

En este rápido consejo aprenderemos cómo personalizar la salida generada por NSLog para depurar programas de manera más eficiente. Sigue leyendo!


Problema

De forma predeterminada, NSLog muestra la salida en el siguiente formato:

 Fecha Hora OurApp [] Salida NSLog

Un ejemplo del mundo real podría verse así:

 2013-08-03 00: 35: 53.038 TestApp [460: c07] Valor del resultado = 20

La salida predeterminada es buena, pero deja algo que desear. La mayoría de las veces, queremos ver lo siguiente en una declaración de registro:

  • Nombre del archivo fuente donde se llamó a NSLog ()
  • Número de línea del código fuente donde se llamó a NSLog ()
  • Nombre de la clase y método donde se llamó a NSLog ()
  • Ocultar la fecha y hora, el nombre de la aplicación y la información de proceso
  • Habilitar / deshabilitar la información de registro cambiando el modo (por ejemplo, depurar, liberar, preparar)

En resumen, nos gustaría que NSLog se pareciera más a esto:

 (ClassName MethodName) (SourceFileName: LineNumber) Salida de NSLog

Solución

Veamos primero cómo funciona NSLog inalterado. NSLog es solo una función C incorporada en el marco de cimientos de Cocoa, y se comporta como cualquier otra función variadic C. Específicamente, NSLog envía mensajes de error al servicio de registro del sistema Apple. Lo hace simplemente pasando sus argumentos a lo largo de la función NSLogv.

Dado que NSLog es solo un contenedor para NSLogv, podemos redefinir NSLog con nuestra propia llamada personalizada a NSLogv. Eso es exactamente lo que te mostraré cómo hacerlo en este tutorial..


1. Iniciar un nuevo proyecto

Crea un nuevo proyecto iOS en Xcode, con el Aplicación vacía modelo. Llámalo ExtenderNSLog. Marque la opción para el conteo automático de referencias, pero desmarque las opciones para Core Data y Unit Tests..

Crear un proyecto de iOS con la plantilla de aplicación vacía El nombre del producto debe ser "ExtendNSLog"

2. Crea una clase Objective-C

Ahora crea un archivo de encabezado junto con el proyecto. Seleccionar Nuevo archivo> Objetivo - Clase C. Establezca el nombre de la clase en ExtendNSLogFunctionality. que será una subclase de NSObject.

Crear un objetivo - plantilla de clase C Establezca el nombre de la clase en ExtendNSLogFunctionality

3. Agregue la lógica NSLog personalizada

Paso 1

Abierto ExtendNSLogFunctionality.h y coloque el siguiente código dentro del encabezado:

 #importar  #ifdef DEBUG #define NSLog (args…) ExtendNSLog (__ FILE __, __ LINE __, __ PRETTY_FUNCTION __, args); #else #define NSLog (x…) #endif void ExtendNSLog (const char * file, int lineNumber, const char * functionName, NSString * format,…);

El condicional anterior definirá un NSLog declaración solo cuando se define DEBUG. Cuando DEBUG no está definido, la instrucción NSLog no hará nada. Surge la pregunta: ¿cómo se controla cuando se define DEBUG? Esto se puede hacer asignando DEBUG = 1 en la configuración del preprocesador para su proyecto.

Para hacerlo, haga clic en el objetivo de su aplicación y seleccione la pestaña Configuración de compilación. A continuación, asegúrese de que las opciones "Todos" y "Combinadas" estén seleccionadas. Busque "preprocesamiento" y localice la sección titulada "Macros de preprocesador". A continuación, simplemente agregue "DEBUG = 1" a la sección de depuración.

Agregue el indicador DEBUG = 1 a la configuración del preprocesador

Tenga en cuenta que en las plantillas de proyectos Xcode más recientes, ya habrá una macro DEBUG = 1 definida para la configuración de compilación de depuración en la sección de macros del preprocesador. Para obtener más información, consulte esta publicación en StackOverflow.

Paso 2

Con la macro de depuración definida, nuestra próxima tarea es escribir la versión personalizada de NSLog. Abra ExtendNSLogFunctionality.m y agregue el siguiente código:

 #import "ExtendNSLogFunctionality.h" void ExtendNSLog (const char * file, int LineNumber, const char * functionName, NSString * format, ...) // Escriba para contener información sobre los argumentos de las variables. va_list ap; // Inicializar una lista de argumentos variables. va_start (ap, formato); // NSLog solo agrega una nueva línea al final del formato NSLog si // ya no está allí. // Aquí estamos utilizando esta función de NSLog () si (! [Format hasSuffix: @ "\ n"]) format = [format stringByAppendingString: @ "\ n"];  NSString * body = [[NSString alloc] initWithFormat: formatea los argumentos: ap]; // Finalizar usando la lista de argumentos variables. va_end (ap); NSString * fileName = [[NSString stringWithUTF8String: file] lastPathComponent]; fprintf (stderr, "(% s) (% s:% d)% s", functionName, [fileName UTF8String], lineNumber, [body UTF8String]); 

Paso 3

Ahora agregue ExtendNSLogFunctionality.h include al archivo de encabezado de prefijo Prefix.pch dentro de la sección #ifdef __OBJC__.

 #ifdef __OBJC__ #import  #importar  #import "ExtendNSLogFunctionality.h" #endif

Para una mejor comprensión de los encabezados de prefijo, eche un vistazo a esta entrada en Wikipedia. Con respecto a las mejores prácticas de encabezado de prefijo, consulte esta publicación de StackOverflow.


4. Un ejemplo de registro personalizado

Ahora agregue un NSLog en cualquier lugar en el código de su proyecto. En mi caso, decido agregar uno dentro del método AppDelegate.m's -Aplicación (BOOL): (UIApplication *) aplicación didFinishLaunchingWithOptions: (NSDictionary *) launchOptions.

 resultado int = 20; NSLog (@ "Valor del resultado:% d", resultado);

Si crea y ejecuta el proyecto con la configuración de depuración ahora, debería ver algo como esto:

 (- [Aplicación AppDelegate: didFinishLaunchingWithOptions:]) (AppDelegate.m: 21) Valor del resultado: 20

¡Aclamaciones! Esta salida es mucho más útil que la implementación predeterminada. Esperamos que encuentre que esta técnica le ahorrará mucho tiempo al depurar sus propios programas.!