如何找出谁叫方法?

时间:2009-11-25 00:51:21

标签: objective-c cocoa cocoa-touch

示例:当调用我的方法-fooBar时,我希望它在控制台中登录其他类所谓的其他方法。

现在,我只知道如何记录fooBar本身及其类的方法名称,其中包含:

_cmd

[self class]

这有可能搞清楚吗?

8 个答案:

答案 0 :(得分:35)

在完全优化的代码中,没有100%可靠的方法来确定某个方法的调用者。编译器可以使用尾调用优化,而编译器有效地重用调用者的堆栈帧用于被调用者。

要查看此示例,请使用gdb在任何给定方法上设置断点,然后查看回溯。请注意,在每次方法调用之前都没有看到objc_msgSend()。这是因为objc_msgSend()对每个方法的实现进行尾调用。

虽然您可以编译未优化的应用程序,但您需要所有系统库的非优化版本才能避免这一问题。

这只是一个问题;实际上,你问“我如何重新发明CrashTracer或gdb?”。一个非常难以解决的职业问题。除非你想要“调试工具”成为你的职业,否则我建议不要走这条路。

你真的想回答什么问题?

答案 1 :(得分:6)

this

怎么样?
NSString *sourceString = [[NSThread callStackSymbols] objectAtIndex:1];

NSCharacterSet *separatorSet = [NSCharacterSet characterSetWithCharactersInString:@" -[]+?.,"];
NSMutableArray *array = [NSMutableArray arrayWithArray:[sourceString  componentsSeparatedByCharactersInSet:separatorSet]];
[array removeObject:@""];

NSLog(@"Class caller = %@", [array objectAtIndex:3]);
NSLog(@"Method caller = %@", [array objectAtIndex:4]);

原作者intropedro的致谢。

答案 2 :(得分:3)

在没有实际行走堆叠的情况下,一般情况下是不可能的。甚至没有保证另一个对象发送调用该方法的消息。例如,它可以从信号处理程序中的块调用。

答案 3 :(得分:2)

请参阅backtrace(3)

答案 4 :(得分:2)

使用以下方法
传递要显示方法的索引,如果要显示完整的方法堆栈

,则传递-1
+(void) methodAtIndex:(int)index{
    void* callstack[128];
    int frames = backtrace(callstack, 128);
    char** strs = backtrace_symbols(callstack, frames);

    if (index == -1) {
        for (int i = 0; i < frames; ++i) {
            printf("%s\n", strs[i]);
        }
    }
    else {
        if (index < frames) {
            printf("%s\n", strs[index]);
        }
    }
    free(strs);

}

答案 5 :(得分:2)

NSLog(@"Show stack trace: %@", [NSThread callStackSymbols]);

答案 6 :(得分:1)

可以使用DTrace获取此信息。

答案 7 :(得分:1)

创建一个宏,将函数名称__FUNCTION__添加到函数调用中。然后,该宏将使用char *的额外参数调用您的函数到目标函数。