Советы по отладке Objective-C в Xcode4?

Исходя из среды разработки Flex-Flash, я смог установить точки останова в своем коде и во время выполнения просматривать значения моих переменных в соответствующем окне.

Теперь я выяснил, где я могу найти окно «переменных» в Xcode, и я могу видеть там все свои переменные, НО значения этих переменных не видны. Все, что у меня есть, это тип данных и куча шестнадцатеричных чисел (указатели?).

Как мне отлаживать свой код? Где я могу увидеть значения моих переменных, не записывая их в свой код?

Я пытаюсь увидеть значения NSDictionary с набором пар ключ / значение. Но также и любой другой NSObject в этом отношении. Я что-то читал о переопределении метода описания, но как насчет собственных объектов?

16
задан Monolo 21 February 2012 в 15:36
поделиться

1 ответ

Отладка с помощью GDB

XCode предоставляет вам отладчик GDB, поэтому, как сказал Яно в своем комментарии, вы можете использовать команды GDB, такие как po (print object), для просмотра объекта.

po myObject
po myDictionary
po myArray

Для печати примитивов, таких как int, float, вы можете использовать print, p и px (для просмотра числа в шестнадцатеричном формате)

print myInt
p myInt
px myInt

Вы также можете увидеть результат выполнения команд. Например, чтобы просмотреть длину строки, вы можете сделать:

p (int) [myString length]

Если вы не приведете return к int, я думаю, вы увидите некоторые жалобы в консоли.

Чтобы просмотреть фрейм UIView (тип структуры CGRect), вы можете сделать:

p (CGRect) [myView frame]

Наконец, если вы переопределите метод класса description, вы можете настроить его отображение при записи в консоль или даже NSLog по этому вопросу. Если вы сделаете [NSString stringWithFormat:@"My object... %@", myObj], будет вызван метод описания этого объекта.

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

Другое хорошее чтение - Как установить условную точку останова в XCode на основе свойства строки объекта?


Подсказка журнала

Если вы вам нужны сообщения NSLog, но только в отладочных сборках, вам может понравиться макрос DLog, который мы используем в моей работе:

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

Он работает так же, как NSLog, за исключением того, что он компилируется в сборках, отличных от DEBUG. NSLog может на самом деле повлиять на производительность, плюс вам может не потребоваться, чтобы некоторые сообщения появлялись в ваших журналах.

Мы поместили этот макрос в предварительно скомпилированный заголовочный файл (MyApp-Prefix.pch), чтобы он был включен во все файлы проекта.


Dumping Variables

Ваш комментарий спросил о том, как вывести все переменные объекта без написания кода. Я не знаю ни одного встроенного способа сделать это. Тем не менее, вы можете попробовать использовать отражение. У меня есть реализация, которая позволит вам сделать что-то вроде:

po [someObj dump]

Вы можете создать категорию для NSObject, чтобы добавить метод ко всем типам NSObject, который будет выводить информацию, которую вы ищете. Я позаимствовал код из Objective C Introspection / Reflection , чтобы запустить код, но добавил код для включения значений свойств.

Категория NSObject (DebuggingAid):

#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
39
ответ дан 30 November 2019 в 16:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: