如何logging在iOS应用程序中使用的所有方法

我正在接pipe客户端的iPad应用程序的开发。 有大量的工作已经完成,我正在试图拼凑整个事情是如何运行的。

我想要做的事情之一是logging当应用程序运行时调用哪些方法。 我见过一个自定义的DTrace脚本,意在logging启动时的所有方法,但是当我在Instruments中运行它时,我没有得到任何结果。

logging这些方法的最好方法是什么?

受到tc对类似问题的回答的启发,我将一个debugging断点操作放在一起,每次在应用程序中触发objc_msgSend()时,都会注销类和方法名称。 这与我在这个答案中描述的DTrace脚本类似。

要启用此断点操作,请创build一个新的符号断点(在Xcode 4中,转到断点导航器,并使用窗口左下angular的加号创build一个新的符号断点)。 将符号设置为objc_msgSend ,将其设置为在评估操作后自动继续,并使用以下命令将操作设置为debugging器命令:

 printf "[%s %s]\n", (char *)object_getClassName(*(long*)($esp+4)),*(long *)($esp+8) 

你的断点应该如下所示:

断点行动

当你的应用程序运行时,这应该注销这样的消息:

 [UIApplication sharedApplication] [UIApplication _isClassic] [NSCFString getCString:maxLength:encoding:] [UIApplication class] [SLSMoleculeAppDelegate isSubclassOfClass:] [SLSMoleculeAppDelegate initialize] 

如果你想知道我在哪里取内存地址,请阅读这篇关于Objective-C运行时内部的Phrack文章 。 上面的内存地址只对Simulator有效,所以你可能需要调整这个设置才能在iOS设备上运行。 Collin在他的答案中提出了以下修改,以便在设备上运行:

 printf "[%s %s]\n", (char *)object_getClassName($r0),$r1 

另外,我想你会发现注销应用程序中调用的每个方法都会使信息压倒你。 您可能可以使用一些条件来过滤,但是我不知道这是否会帮助您了解您的代码执行情况。

如果您使用LLDB,则需要使用以下debugging器命令。 这些在Xcode 4.6中进行了testing。

设备:

 expr -- (void) printf("[%s %s]\n", (char *)object_getClassName($r0),$r1) 

模拟器:

 expr -- (void) printf("[%s %s]\n", (char *)object_getClassName(*(long*)($esp+4)), *(long *)($esp+8)) 

Brad Larson的方法可以通过使用debugging器命令来适应在设备上运行:

 printf "[%s %s]\n", (char *)object_getClassName($r0),$r1 

更多信息可以在技术说明中find: 技术说明

要跟踪设备上的Xcode 6下的应用程序代码,我必须使用以下debugging器expression式。

 expr -- (void) printf("[%s %s]\n", (char *)object_getClassName($arg1),$arg2) 

后来的xcode版本,你需要像这样调用

 expr -- (void)printf("[%s, %s]\n",(char *) object_getClassName(*(long*)($esp+4)), (char *) *(long *)($esp+8) ) 

如果你想限制输出到只发送给一个类的消息,你可以添加一个这样的条件

(int)strcmp((char *)object_getClassName($ r0),“NSString”)== 0

一位开发人员教会我为每种方法添加相同的两个日志语句。 一个作为第一行,另一个作为最后一行。 我认为他有一个脚本可以自动完成他的项目,但结果是:

 NSLog(@"<<< Entering %s >>>", __PRETTY_FUNCTION__); NSLog(@"<<< Leaving %s >>>", __PRETTY_FUNCTION__); 

在控制台,这将吐出像这样的东西:

  <<< Entering -[MainListTableViewController viewDidLoad] >>> 

跟踪正在发生的事情非常有帮助。

如果您想要在64位模拟器中logging方法,请改用以下命令:

 expr -- (void) printf("[%s %s]\n", (char *)object_getClassName($rdi), (char *) $rsi) 

或者如果这不起作用,请按照以下方式logging:

在这里输入图像描述

主要思想是使用$ rdi作为对象(self),$ rsi作为select器。

 NSLog(@"%@", NSStringFromSelector(_cmd)); 

要么

 NSLog(@"%s", __PRETTY_FUNCTION__);