Anatoliy Gatt
Anatoliy Gatt

Reputation: 2491

How to know which method performed selector in Objective-C

I have really simple example, but I can't understand how I could get information about the method that call selector inside it. For example:

-(void)methodOne {
   [self performSelector:@selector(methodTwo:)];
}
-(void)methodTwo:(id)sender {
   //How to know which method performed selector???
}

I think this example is pretty simple, I just need to understand this, again, the question is, how could I know from methodTwo: which method perform selector, so from which method I called methodTwo:.

Thanks in advance!

Upvotes: 2

Views: 1545

Answers (3)

Constantino Tsarouhas
Constantino Tsarouhas

Reputation: 6886

You can't know from the second method which method called it, at least not without going through the call stack (see NSThread) but you can pass this information from the first method like this:

- (void)doSomething {
    [self doSomethingElseWithCallee: NSStringFromSelector(_cmd) andSender: self];
}

- (void)doSomethingElseWithCallee: (NSString *)selector andSender: (id)sender] {
    // Do something…
}

Or you could just pass the selector (of type SEL) right away, instead of a string:

- (void)doSomething {
    [self doSomethingElseWithCallee: _cmd andSender: self];
}

- (void)doSomethingElseWithCallee: (SEL)selector andSender: (id)sender] {
    // Do something…
}

By the way, _cmd is a special argument that the Objective-C runtime passes to your method, along with self (the current object). They're not included in your method signature, but the compiler does all the work for you. ;-)

All hail the Objective-C language! :-p

Upvotes: 1

zrzka
zrzka

Reputation: 21249

If you do want to know which method calls your methodTwo, you can look at call stack. Look at this ...

-(void)methodOne {
  [self performSelector:@selector(methodTwo:)];
}

-(void)methodTwo:(id)sender {
  NSLog( @"%@", [NSThread callStackSymbols][1]);
  NSLog( @"%@", [NSThread callStackSymbols][2]);
}

... and the log output (simplified) is ...

0x014ef671 -[NSObject performSelector:] + 62
0x00002307 -[CMAppDelegate methodOne] + 55

... callStackSymbols returns NSArray with call stack symbols, so, you can look at index 1 to get method which did you call your method. As you can see, there's NSObject's performSelector and it's because you called methodTwo via performSelector. If you change your methodOne in this way ...

-(void)methodOne {
  [self methodTwo:nil];
}

... the output is ...

0x000022fe -[CMAppDelegate methodOne] + 62
0x000025d6 -[CMAppDelegate application:didFinishLaunchingWithOptions:] + 374

... that's it. Your question is answered, but I dunno why do you want this. You probably don't want to know which method exactly did call your method, but which object initiated this call chain. An example is button - you can have one method to handle more buttons and there's sender argument to distinguish between these buttons as @stavash pointed out.

Upvotes: 6

Stavash
Stavash

Reputation: 14314

Try using performSelector:withObject:

-(void)methodOne {
   NSString *identifierStr = @"methodOne";
   [self performSelector:@selector(methodTwo:) withObject:identifierStr];
}
-(void)methodTwo:(NSString *)senderIdentifierStr {
   NSLog(@"Sent by %@",senderIdentifierStr);
}

Upvotes: 2

Related Questions