2010-11-28 146 views

回答

30

你的問題是,你聲明的委託實例變量:

id<SomeProtocol> delegate; 

,對嗎?那麼,這意味着編譯時檢查器只會尋找<SomeProtocol>協議中的方法。但是,performSelector:withObject:afterDelay:NSObject上聲明。這意味着你應該聲明爲伊娃:

NSObject<SomeProtocol> * delegate; 

這是說,它必須是一個NSObject符合<SomeProtocol>,而不是符合<SomeProtocol>任何對象。這應該擺脫你的警告,你不必做任何演員。

3

嘗試第一投射委託其類的類型,然後調用performSelector:withObject:afterDelay

[(SomeClass *) delegate performSelector:@selector(doStuff:) withObject:myObject afterDelay:2.0]; 

假設你delegateid類型的,你需要告訴實際上對象也從NSObject繼承運行(其中定義了performSelector:withObject:afterDelay:方法)將其轉換爲類的類型。

+1

任何對象將始終從NSObject繼承(一切都會,它是一個根類)。我認爲你的意思是符合NSObject協議。 – 2010-11-28 03:11:02

+1

@Evan一切都不會*從NSObject繼承。而'performSelector:withObject:afterDelay:`在NSObject協議中沒有定義,它在`NSObject`類中定義。 – 2010-11-28 03:12:49

+1

鑄造破壞封裝。如果這是針對代表類型未知的類的情況呢? – 2010-11-28 03:21:01

2

您需要將委託對象轉換爲您正在使用的實際類以獲得方法。查看委託只能顯示協議中定義的方法。 performSelector:withObject:不是在協議中定義的方法。

[(CLASS*)delegate performSelector:@selector(doStuff:) withObject:myObject afterDelay:2.0]; 
1
[NSTimer scheduledTimerWithTimeInterval:2 
    target:self 
    selector:@selector(doStuff) 
    userInfo:nil 
    repeats:NO]; 

嘗試是假設你只想要一個計時器

3

儘管Dave提出的NSObject *可以工作,但有一種更清晰的替代方式,可以讓人們按照預期使用協議 - 您可以讓協議本身聲明它支持NSObject協議。

NSObject不僅僅是一個實現,而且是一個包含所有performSelector:方法變體的協議。所以,你可以在你的協議只是聲明自己支持NSObject的,就像您的任何其他類支持的協議:

@protocol MyProtocol <NSObject> 

,編譯器警告將消失(假設你已經進口協議定義)。

請注意,這確實意味着任何聲明支持您的協議的人都必須是NSObject或繼承很多方法。但是,由於實際考慮,iPhone編程中使用的所有類都是從NSObject派生的,所以這通常不是問題。

編輯:

原來的-performSelector:withObject:afterDelay:不在NSObject的協議(無延遲的有)。因爲如果每個人都使用你的協議,如果他們可以使用id來引用一個協議類型,它仍然更好,我仍然會使用一個協議來解決這個問題 - 但是你必須自己聲明一個NSObject協議的擴展。因此,在文件的標題中,您可以添加如下內容:

@protocol MyProtocolNSObjectExtras <NSObject> 
- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay; 
@end 

@protocol MyProtocol <NSObjectExtras> 
.... 
@end 

然後,您將獲得與前面所述相同的所有優點。