Xcode4中的Objective-C调试技巧?

Jov*_*van 16 debugging macos objective-c ios xcode4

来自Flex-Flash IDE,我能够在我的代码中设置断点,并在运行时查看相应窗口中变量的值.

现在,我想出了我可以在Xcode中找到"变量"窗口的位置,我可以在那里看到所有变量但是这些变量的值无法看到.我只有数据类型和一堆十六进制数字(指针?).

我该怎么调试我的代码?我在哪里可以看到我的变量的值而无需在我的代码中记录它们?

我试图NSDictionary用一堆键/值对来查看a的值.但也是其他任何NSObject事情.我已经阅读了一些有关覆盖描述方法的内容但是本机对象呢?

Sam*_*Sam 39

使用GDB进行调试

XCode为您提供了一个GDB调试器,就像Jano在他的评论中所说,您可以使用像po(打印对象)这样的GDB命令来查看对象.

po myObject
po myDictionary
po myArray
Run Code Online (Sandbox Code Playgroud)

要打印喜欢整数,浮点元,就可以使用print,p以及px(查看以十六进制)

print myInt
p myInt
px myInt
Run Code Online (Sandbox Code Playgroud)

您还可以查看运行命令的结果.例如,要查看字符串长度,您可以执行以下操作:

p (int) [myString length]
Run Code Online (Sandbox Code Playgroud)

如果你没有将返回值转换为int,我相信你会在控制台中看到一些抱怨.

要查看UIView的框架(CGRect结构类型),您可以执行以下操作:

p (CGRect) [myView frame]
Run Code Online (Sandbox Code Playgroud)

最后,如果覆盖description类的方法,则可以自定义在写入控制台或甚至NSLog时的显示方式.如果你这样做[NSString stringWithFormat:@"My object... %@", myObj],将调用该对象的描述方法.

- (NSString*) description
{
   return @"This is the object description!";
}
Run Code Online (Sandbox Code Playgroud)

另一个好的读物是如何根据对象字符串属性在Xcode中设置条件断点?


日志提示

如果您想要NSLog消息但仅在调试版本中,您可能会喜欢DLog我在工作中使用的宏:

#ifdef DEBUG
    #define DLog(...) NSLog(__VA_ARGS__)
#else
    #define DLog(...) /* */
#endif
Run Code Online (Sandbox Code Playgroud)

它的工作方式与NSLog类似,不同之处在于它是在非DEBUG构建版本上编译的.NSLog实际上可能会受到性能影响,而且您可能不希望某些消息在您的日志中溢出.

我们将此宏放在预编译的头文件(MyApp-Prefix.pch)中,以便它包含在所有项目文件中.


倾倒变量

您的评论询问如何在不编写代码的情况下转储对象的所有变量.我知道没有内置的方法来做到这一点.但是,您可以尝试使用反射.我有一个实现,可以让你做类似的事情:

po [someObj dump]
Run Code Online (Sandbox Code Playgroud)

您可以在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
Run Code Online (Sandbox Code Playgroud)


Tom*_*mmy 5

假设您已设置断点并且程序已停止,您将在调试区域左侧的变量视图中看到变量列表.每个都有一个值.如果它是一个原始类型,那么没有什么可看的,但如果它是一个对象,你得到的只是地址和披露箭头.公开箭头将显示对象的所有实例变量.通过这种方式,您可以深入了解您正在寻找的任何内容.

很多时候你有对象公开一个属性的getter但是没有显式存储或者以另一种形式存储它.调试器不够智能,无法遵循这些,但您可以在右侧的GDB窗口中评估所需的任何Objective-C表达式,包括执行方法调用.在我看来,最有用的命令是'p'来打印原始对象,'po'来打印对象类型的描述.

在基础类型中,变量视图窗口看起来足够聪明,能够列出NSArray的内容,但不够聪明,无法为您提供有关字典的任何有意义的内容.你被告知例如'1键/值对',但仅此而已.所以你被困在右边的窗口,输入'po dictionary'来查看内容.

我个人认为Xcode中的图形状态检查非常弱; 我发现调试器完全有效,并且可以轻松跟踪我的代码并发现错误,因为我已经学会使用右侧的控制台窗口.

  • +1"Xcode中的图形状态检查非常弱" (5认同)