2012-07-21 29 views
2

我有一個非常簡單的示例,但我無法理解如何獲取有關調用其中的選擇器的方法的信息。例如:如何知道在Objective-C中執行選擇器的方法C

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

我覺得這個例子很簡單,我只需要明白這一點,再次,問題是,我怎麼可能從methodTwo知道:哪種方法進行選擇,所以從該方法我稱爲方法二:

在此先感謝!

回答

6

如果你想知道哪些方法調用你的methodTwo,你可以看看調用堆棧。看看這個......

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

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

...和日誌輸出(簡體)是...

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

... callStackSymbols回報NSArray與調用堆棧符號,所以,你可以看看在索引1處獲得你稱之爲方法的方法。正如你所看到的,有NSObjectperformSelector,這是因爲你通過performSelector調用methodTwo。如果你改變這種方式你methodOne ...

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

...輸出是...

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

...就是這樣。你的問題得到解答,但我不知道爲什麼你想要這個。你可能不想知道哪個方法確實調用了你的方法,但是哪個對象啓動了這個調用鏈。一個例子是按鈕 - 你可以有一個方法來處理更多的按鈕,並有sender參數來區分@stavash指出的這些按鈕。

+0

似乎你在我還在打字時在我面前提到了'NSThread'的調用堆棧方法! :-P – 2012-07-21 09:11:09

2

嘗試使用performSelector:withObject:

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

有一個'performSelector:withObject:'你可以使用。 '... afterDelay:0.0'位是多餘的。 – 2012-07-21 08:54:33

+0

你說得對,我在看NSObject文檔,它只有「afterDelay:」版本,儘管NSObject協議文檔也有縮短版本。奇怪,不是嗎? – Stavash 2012-07-21 08:59:04

+1

不,它在文檔中。你在混合兩件事 - NSObject類和NSObject協議。兩者都存在。 – robertvojta 2012-07-21 09:55:16

1

不能從第二個方法,該方法被稱爲它,至少在沒有通過調用堆棧會(見NSThread)知道,但你可以從這樣的第一種方法傳遞這樣的信息:

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

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

或者你可以只通過(SEL類型)選擇向右走,而不是字符串:

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

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

順便說一句,_cmd是Objective-C的運行時間傳遞給你的方法,以及特殊參數self(當前對象)。它們不包含在你的方法簽名中,但編譯器會爲你做所有的工作。 ;-)

所有的歡呼都是Objective-C語言! :-p

相關問題