Objective-C Советы по отладке в Xcode4? - PullRequest
16 голосов
/ 04 октября 2011

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

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

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

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

Ответы [ 2 ]

39 голосов
/ 04 октября 2011

Отладка с помощью 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), чтобы он был включен во все файлы проекта.


Сброс переменных

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

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
5 голосов
/ 04 октября 2011

Предполагая, что вы установили точку останова и ваша программа остановилась на ней, вы увидите список переменных в представлении переменных в левой части области отладки.У каждого есть значение.Если это примитивный тип, то больше ничего не видно, но если это объект, все, что вы получите, это адрес и стрелку раскрытия.Стрелка раскрытия покажет вам все переменные экземпляра объекта.Таким образом, вы можете перейти к тому, что ищете.

Довольно часто у вас есть объекты, которые предоставляют геттер для свойства, но не сохраняют его явно или сохраняют в другой форме.Отладчик не достаточно умен, чтобы следовать им, но вы можете оценить любое выражение Objective-C, которое вы хотите в правом окне GDB, включая выполнение вызовов методов.На мой взгляд, наиболее полезными командами являются «p» для печати примитивного объекта и «po» для печати описания типа объекта.

Из типов Foundation окно представления переменных выглядит достаточно умным, чтобыбыть в состоянии перечислить содержимое NSArray, но не достаточно умен, чтобы дать вам что-нибудь значимое о словаре.Вам говорят, например, «1 пара ключ / значение», но не более того.Так что вы застряли, заходя в окно справа и набирая 'словарь', чтобы увидеть содержимое.

Мое личное мнение таково, что проверка графического состояния в XCode очень слабая;Я считаю, что отладчик полностью эффективен и может легко отслеживать мой код и находить ошибки только потому, что я научился использовать окно консоли справа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...