Objective-C find caller of method

Viewed 35663

Is there a way to determine the line of code a certain method was called from?

12 Answers

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]);

The Swift 4 version of @Geoff H answer for copy and pasting ;]

let sourceString: String = Thread.callStackSymbols[1]
let separatorSet :CharacterSet = CharacterSet(charactersIn: " -[]+?.,")
var array = Array(sourceString.components(separatedBy: separatorSet))
array = array.filter { $0 != "" }

print("Stack: \(array[0])")
print("Framework:\(array[1])")
print("Memory Address:\(array[2])")
print("Class Caller:\(array[3])")
print("Method Caller:\(array[4])")

Back in the days there where no dot syntax in objective-C, so nowadays it could look like.

#define __UGLY__CALLEE__(idx) fprintf(stderr,"\n%s <- %s",__PRETTY_FUNCTION__,(NSThread.callStackSymbols.count>idx?((NSString*)NSThread.callStackSymbols[idx]).UTF8String:"no callStackSymbol with this index"))

just prints what is needed, no extra re-creation of NSArray or Mutables. Apart from the characters to output and an index to chose this lets you repeat with different stack symbols and prints without timestamp. Extra formatting the output does not only loose performance until you get what you need to know about your method calls it also makes the thing kinda un-flexible. And most important not introducing another method call to self just to ask for the last callee.

__UGLY__CALLEE__(1); results in...

-[Some inspectedMethod] <- 1   Appname                             0x00000001000e6cd2 -[SomeCallee method] + 1234

And as it is not pretty - it is called ugly.

Related