Objective-C Consejos de debugging en Xcode4?

Viniendo de un Flex-Flash IDE, pude establecer puntos de interrupción en mi código y, en time de ejecución, ver los valores de mis variables en la window correspondiente.

Ahora, me di count de dónde puedo encontrar la window 'variables' en Xcode y puedo ver todas mis variables allí, PERO los valores de esas variables no se pueden ver. Todo lo que tengo es el tipo de datos y un grupo de numbers hexadecimales (¿pointers?).

¿Cómo se supone que debo depurar mi código? ¿Dónde puedo ver los valores de mis variables sin tener que ingresarlos en mi código?

Estoy intentando ver los valores de un NSDictionary con un grupo de pares key / valor. Pero también cualquier otro NSObject para ese asunto. He leído algo sobre anular el método de descripción, pero ¿qué pasa con los objects nativos?

Depuración con GDB

XCode le da un depurador de GDB, así como Jano dijo en su comentario, puede usar commands de GDB como po (object de printing) para ver un object.

 po myObject po myDictionary po myArray 

Para imprimir primitivas como int, float, puede usar print , p y px (para ver el número en hexadecimal)

 print myInt p myInt px myInt 

También puede ver el resultado de ejecutar commands. Por ejemplo, para ver una longitud de cadena puede hacer lo siguiente:

 p (int) [myString length] 

Si no arrojas el retorno a un int, creo que verás algunas quejas en la console.

Para ver el marco de una UIView (tipo de estructura CGRect), puede hacer lo siguiente:

 p (CGRect) [myView frame] 

Por último, si anula el método de description de una class, puede personalizar cómo se muestra cuando se escribe en la console o incluso a un NSLog para ese asunto. Si haces [NSString stringWithFormat:@"My object... %@", myObj] al método de descripción de ese object.

 - (NSString*) description { return @"This is the object description!"; } 

Otra buena lectura es Cómo establecer un punto de interrupción condicional en Xcode basado en una propiedad de cadena de objects.


Consejo de logging

Si desea recibir posts de NSLog pero solo en comstackciones de debugging, puede que le guste la macro DLog que utilizamos en mi trabajo:

 #ifdef DEBUG #define DLog(...) NSLog(__VA_ARGS__) #else #define DLog(...) /* */ #endif 

Funciona igual que NSLog, excepto que se comstack en comstackciones que no sean DEBUG. NSLog realmente puede ser un éxito de performance, además de que puede que no desee que se desparguen algunos posts en sus loggings.

Ponemos esta macro en el file de encabezado precomstackdo (MyApp-Prefix.pch) para que se incluya en todos los files de proyecto.


Variables de dumping

Su comentario le preguntó sobre cómo volcar todas las variables de un object sin escribir código. No conozco ninguna forma incorporada de hacer esto. Sin embargo, puede intentar usar la reflexión. Tengo una implementación que te permitirá hacer algo como:

 po [someObj dump] 

Puede hacer una categoría en NSObject para agregar un método a todos los types de NSObject que volcarán la información que busca. Tomé prestado el código de Objective C Introspection / Reflection para comenzar el código, pero agregué código para include valores de propiedad.

NSObject (DebuggingAid) categoría:

 #import <objc/runtime.h> @interface NSObject (DebuggingAid) - (NSString*)dump; @end @implementation NSObject (DebuggingAid) - (NSString*)dump { if ([self isKindOfClass:[NSNumber class]] || [self isKindOfClass:[NSString class]] || [self isKindOfClass:[NSValue class]]) { return [NSString stringWithFormat:@"%@", self]; } Class class = [self class]; u_int count; Ivar* ivars = class_copyIvarList(class, &count); NSMutableDictionary* ivarDictionary = [NSMutableDictionary dictionaryWithCapacity:count]; for (int i = 0; i < count ; i++) { const char* ivarName = ivar_getName(ivars[i]); NSString *ivarStr = [NSString stringWithCString:ivarName encoding:NSUTF8StringEncoding]; id obj = [self valueForKey:ivarStr]; if (obj == nil) { obj = [NSNull null]; } [ivarDictionary setObject:obj forKey:ivarStr]; } free(ivars); objc_property_t* properties = class_copyPropertyList(class, &count); NSMutableDictionary* propertyDictionary = [NSMutableDictionary dictionaryWithCapacity:count]; for (int i = 0; i < count ; i++) { const char* propertyName = property_getName(properties[i]); NSString *propertyStr = [NSString stringWithCString:propertyName encoding:NSUTF8StringEncoding]; id obj = [self valueForKey:propertyStr]; if (obj == nil) { obj = [NSNull null]; } [propertyDictionary setObject:obj forKey:propertyStr]; } free(properties); NSDictionary* classDump = [NSDictionary dictionaryWithObjectsAndKeys: ivarDictionary, @"ivars", propertyDictionary, @"properties", nil]; NSString *dumpStr = [NSString stringWithFormat:@"%@", classDump]; return dumpStr; } @end 

Suponiendo que haya establecido un punto de interrupción y que su progtwig se haya detenido, verá una list de variables en la vista de variables dentro de la parte izquierda del área de debugging. Cada uno tiene un valor. Si es un tipo primitivo, entonces no hay nada más que ver, pero si es un object todo lo que obtienes es la dirección y una flecha de divulgación. La flecha de divulgación le mostrará todas las variables de instancia del object. De esta forma, puedes profundizar en lo que buscas.

Buena parte del time tiene objects que exponen un getter para una propiedad, pero no lo almacenan explícitamente ni lo almacenan de otra forma. El depurador no es lo suficientemente inteligente como para seguirlos, pero puede evaluar cualquier expresión de Objective-C que desee en la window de GDB a la derecha, incluida la realización de llamadas a methods. En mi opinión, los commands más útiles son 'p' para imprimir un object primitivo y 'po' para imprimir la descripción de un tipo de object.

De los types de Foundation, la window de vista de variables parece ser lo suficientemente inteligente como para poder enumerar los contenidos de un NSArray pero no lo suficientemente inteligente como para darle algo significativo sobre un dictionary. Se le dice, por ejemplo, '1 key / par de valores', pero nada más que eso. Así que estás atascado yendo a la window de la derecha y escribiendo 'po dictionary' para ver el contenido.

Mi opinión personal es que la inspección del estado gráfico en Xcode es extremadamente débil; Encuentro que el depurador es completamente eficaz y puede rastrear fácilmente mi código y encontrar errores solo porque he aprendido a usar la window de la console a la derecha.