从Flex-Flash IDE转过来后,我可以在代码中设置断点,并在运行时查看相应窗口中变量的值。
现在,我已经找到了Xcode中“变量”窗口,可以看到所有的变量,但是这些变量的值是无法被看到的。我只能看到数据类型和一堆十六进制数(指针?)。
我该如何调试我的代码?在不必记录日志的情况下,我在哪里可以看到我的变量值?
我正在尝试查看一个带有大量键/值对的NSDictionary
的值。但同样适用于任何其他NSObject
。我读到过覆盖描述方法的内容,但原生对象怎么处理?
从Flex-Flash IDE转过来后,我可以在代码中设置断点,并在运行时查看相应窗口中变量的值。
现在,我已经找到了Xcode中“变量”窗口,可以看到所有的变量,但是这些变量的值是无法被看到的。我只能看到数据类型和一堆十六进制数(指针?)。
我该如何调试我的代码?在不必记录日志的情况下,我在哪里可以看到我的变量值?
我正在尝试查看一个带有大量键/值对的NSDictionary
的值。但同样适用于任何其他NSObject
。我读到过覆盖描述方法的内容,但原生对象怎么处理?
XCode提供了GDB调试器,就像Jano在他的评论中所说,你可以使用GDB命令如po(输出对象)来查看一个对象。
po myObject
po myDictionary
po myArray
要打印基本类型如int、float,可以使用print
、p
和px
(以十六进制查看数字)
print myInt
p myInt
px myInt
您也可以查看运行命令的结果。例如,要查看字符串长度,可以执行以下操作:
p (int) [myString length]
p (CGRect) [myView frame]
description
方法,则可以自定义其在控制台或NSLog中写入时的显示方式。如果执行[NSString stringWithFormat:@"My object... %@", myObj]
,那么对象的description
方法将被调用。- (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]
#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
po myDictionary
,你应该能看到最初想要的键/值对。 - Saminfo symbol 0x123456
,其中0x123456应替换为内存地址。这将在该内存地址上输出符号信息(如函数名称)。 - Sam
po objectName
或po [object message]
。对于字典类型,请输入po [dic objectForKey:@"somekey"]
。 - Jano