【问题标题】:Pass all arguments of a method into NSLog将方法的所有参数传递到 NSLog
【发布时间】:2009-11-25 16:03:27
【问题描述】:

我使用NSLog() 将一些内容打印到控制台。有没有办法将所有当前方法的参数传递给 NSLog() 或任何其他函数或方法,而无需显式查看它们中的每一个?

例如,当我将LOGME 放入我的代码时,我已经有一个宏可以将有用的信息打印到控制台。该宏将创建一个对单例类的日志记录方法的调用,并传递几个有用的东西,比如_cmd 和其他东西。

我还想捕获该方法的所有参数并将它们传递给自动打印出来。这可能吗?

【问题讨论】:

    标签: objective-c cocoa-touch cocoa reflection arguments


    【解决方案1】:

    使用 gdb。您可以设置一个断点来记录方法的参数并继续。

    如果你坚持用艰难的方式来做......这当然不简单,但你可以在给定的架构/ABI 上使用堆栈结构,并利用 Objective-C 运行时来确定有多少参数和要寻找什么尺寸。从现在开始,我进入了未知领域;我从来没有这样做过,也不会打扰。所以YMMV...

    在您的方法中,您可以获得Method 结构,然后是参数的数量,然后是每个参数类型及其大小。然后,您可以从self 参数的地址(即&self)遍历堆栈,假设您知道自己在做什么......

    Method method = class_getInstanceMethod([self class], _cmd);
    unsigned nargs = method_getNumberOfArguments(method);
    void *start = &self;
    for(unsigned i = 0; i<nargs; i++) {
      char *argtype = method_copyArgumentType(method, i);
      //find arg size from argtype
      // walk stack given arg zie
      free(argtype);
    }
    

    在此过程中,您必须将 argtype 字符串(使用 Objective-C type encodings)转换为堆栈上每个参数的大小。

    当然,您必须为每种类型派生格式字符串,并使用包含参数的适当变量参数数组调用NSLogv,从它​​们在堆栈上的位置复制。可能比它的价值更多的工作。使用调试器。

    【讨论】:

    • 您不想要self 变量的地址吗?从对象指针 in 开始,self 变量不打印方法的参数;它正在打印对象的实例变量(可能作为垃圾,因为您将使用方法参数类型来进行 [mis] 指导)。
    • 是的,绝对是,从 &self 开始。
    • 这就是我的意思:不应该将start 初始化为&amp;self,而不是self
    • @Peter 当然。将来,您可以随意编辑。我比我更信任你。
    • 很好的答案。但是你能告诉我如何从堆栈中获取值吗?我想实现一个打印出选择器名称和参数值的日志记录例程。只是缺少最后一步;)谢谢。
    【解决方案2】:

    没有办法处理预处理器或 Objective-C 中的所有参数。

    我知道的唯一方法是使用调试器。您可以在 Xcode 中添加断点操作来轻松完成此操作。右键单击代码窗口最左侧的一列,选择“内置断点”->“记录断点和参数并自动继续”。

    【讨论】:

    • 那调试器是怎么做的呢?
    • 调试器了解 ABI(调用约定)并使用调试符号(由编译器创建)将代码和寄存器中的地址映射到源文件中的位置和变量。简而言之:它使用了一大堆不属于语言的技巧。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-24
    • 1970-01-01
    • 2022-06-17
    • 1970-01-01
    相关资源
    最近更新 更多