Objective-C Find Caller of Method

Objective-C find caller of method

StackI hope that this helps:

NSString *sourceString = [[NSThread callStackSymbols] objectAtIndex:1];
// Example: 1 UIKit 0x00540c89 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1163
NSCharacterSet *separatorSet = [NSCharacterSet characterSetWithCharactersInString:@" -[]+?.,"];
NSMutableArray *array = [NSMutableArray arrayWithArray:[sourceString componentsSeparatedByCharactersInSet:separatorSet]];
[array removeObject:@""];

NSLog(@"Stack = %@", [array objectAtIndex:0]);
NSLog(@"Framework = %@", [array objectAtIndex:1]);
NSLog(@"Memory address = %@", [array objectAtIndex:2]);
NSLog(@"Class caller = %@", [array objectAtIndex:3]);
NSLog(@"Function caller = %@", [array objectAtIndex:4]);

How to find out who called a method?

In fully optimized code, there is no 100% surefire way to determine the caller to a certain method. The compiler may employ a tail call optimization whereas the compiler effectively re-uses the caller's stack frame for the callee.

To see an example of this, set a breakpoint on any given method using gdb and look at the backtrace. Note that you don't see objc_msgSend() before every method call. That is because objc_msgSend() does a tail call to each method's implementation.

While you could compile your application non-optimized, you would need non-optimized versions of all of the system libraries to avoid just this one problem.

And this is just but one problem; in effect, you are asking "how do I re-invent CrashTracer or gdb?". A very hard problem upon which careers are made. Unless you want "debugging tools" to be your career, I would recommend against going down this road.

What question are you really trying to answer?

Xcode / Objective-c - How to find the callers of a given method programmatically

Not exactly an answer, but it might help. This methods will give you a printout of stack or of caller in debug area. You can modify them of course to use the values as you please.

Code is kind of 'stolen' but i have no reference to where from.

#define SHOW_STACK NSLog(@"%@",[NSThread callStackSymbols])

#define SHOW_CALLER \
do { \
NSArray *syms = [NSThread callStackSymbols]; \
if ([syms count] > 1) { \
NSLog(@"<%@ %p> %@ - caller: %@ ", [self class], self, NSStringFromSelector(_cmd),[syms objectAtIndex:1]); \
} else { \
NSLog(@"<%@ %p> %@", [self class], self, NSStringFromSelector(_cmd)); \
} \
} while(0)

EDIT: you would probably want something like this:

NSString *caller = nil;
NSArray *syms = [NSThread callStackSymbols];

if (syms.count > 1)
{
caller = syms[1];
}

if (caller.length)
{
NSLog(@"%s called by %@",
__PRETTY_FUNCTION__,
caller);
}

There is another Q&A here on SO you might find very useful.

Finding caller method from called

Although I definitely recommend against doing this (Pass a flag as you suggest yourself), here's how you would see one level up in your call stack:

NSLog(@"%@", [[NSThread callStackSymbols] objectAtIndex:1]);

How to get the caller's class Name in objective C while using inheritance?

No. Methods have no way of knowing from which other object's method they are being called. There's not even the concept of a caller's identity. Methods can be called from a C function where there is no caller object at all.

I need to know from which subclass this method was called.

That being said, you probably just want to know of which (derived) class an object is:

NSLog(@"My class: %@", NSStringFromClass([self class]));

2014 Addendum: There's a gnu extension __builtin_return_address that might be used for this purpose. Mike Ash shows how to use it to extract a callers symbol name (see "Caller Inspection"). I still think that the whole approach is a bit fragile and should only be used for debugging.



Related Topics



Leave a reply



Submit