Подтвердить что ты не робот

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

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

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

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

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

4b9b3361

Ответ 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]

Если вы не вернете возврат к 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

Ответ 2

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

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

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

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