2014-01-29 61 views
3

我想知道ARC在哪裏獲取方法簽名信息來完成其工作。 在下面的代碼中,我向這個對象的父對象發送一條消息,而沒有指定它的類。 如果我不註釋父級伊娃,編譯器會發出警告。 如果我將它轉換爲id,那麼該程序將工作,並且不會發出警告。同樣是真實 如果我使用performSelector:withObject:ARC併發送消息給對象而無需在編譯時指定類

如果父方法是userSelected:不同的,那麼,工程 的唯一事情是performSelector(同時發出警告)。

據我所知,ARC正在從調用self.parent的對象中獲取方法簽名。它是否正確?如果方法簽名存在於發送消息的對象中,您是否可以避免告訴ARC對象是什麼類?

- (void)userSelected:(id)sender 
{ 
    if ([self.parent respondsToSelector:@selector(userSelected:)]) { 

     //1: This fails with error (no visible interface). 
     [self.parent userSelected:self]; 
     //2: This line works without warnings. 
     [(id)self.parent userSelected:self]; 
     //3: This line also works 
     [self.parent performSelector:@selector(userSelected:) 
          withObject:self]; 
} 
+1

什麼是警告? –

回答

2

Wil Shipley在他的刪除答案中是正確的,當時他說這與ARC沒有關係。

您收到的警告是關於接收器的靜態類型(self.parent),而編譯器試圖幫助您阻止將消息發送到不響應此選擇器的對象。換句話說:self.parent的班級不包含userSelected:的聲明。

但編譯器知道一個叫userSelected:方法(在其它的類或類別),因爲它可以讓你發這條短信給一個對象而靜態類型信息。這有點像C語言,可以讓任何類型的指針使用void指針。

所以,所有這些都不是ARC相關的,切換到MRC時不會改變。

編輯:

是,將消息發送到id時,編譯器將認爲任何可見@interface和@protocol找到選擇的聲明。在這種情況下,「可見」意味着任何導入的標題,無論是自定義,框架還是前綴。方法聲明主要需要獲取參數的類型信息。

請注意,ARC行爲僅受非常罕見的情況影響(當聲明包含有關所有權語義的信息時,如objc_method_family等)。

如果編譯器發現衝突的聲明,它會發出錯誤。當試圖編譯...

[(id)nil type]; 

...你會得到...

> error: multiple methods named 'type' found with mismatched result, parameter type or attributes 

...加上一對情侶在UIKit中,基金會和其他框架不同的聲明。

+0

但如果在self.parent上調用的方法是userSelected:沒有警告或失敗。它工作正常。所以我的問題是:編譯器是否在現有文件以及相應的類文件(用於self.parent)中查找方法簽名? ARC(或者,編譯器)能否在所有項目文件中查找選擇器?這個文件中的方法有什麼相同的選擇器,但不同的參數? – theprole

+0

@theprole請參閱編輯。 –