2011-12-05 69 views
12

我需要幫助調試我的類。我遇到了一個很奇怪的錯誤,我找不到任何類似的東西,所以我只想放下大部分代碼。Xcode錯誤:沒有已知的實例方法選擇器

//Tab.h 
#import <UIKit/UIKit.h> 
@class Tab; 
@protocol TabDelegateDataSource <NSObject> 
@required 
-(void)removeTab:(Tab *)tab; 
@end 

@interface Tab : UIView 
{ 
    id <TabDelegateDataSource> __strong _delegate; 
} 

@property(strong) id <TabDelegateDataSource> delegate; 

-(void)removeTab; 

@end 

// Tab.m 
#import "Tab.h" 
@implementation Tab 
@synthesize delegate = _delegate; 
-(void)removeTab 
{ 
    [self.delegate removeTab:self];//Error here saying: No known instance method for selector 'removeTab:' 
} 

@end 
+1

出於好奇,是什麼如果你在違規行上用'_delegate'替換'self.delegate',會發生什麼? – dasblinkenlight

+0

你的委託實際上有一個'removeTab'方法嗎?這個錯誤信息暗示它沒有。嘗試調試和檢查self.delegate,並確保它是你所期望的,並且它有一個'removeTab'方法。 – WilHall

+1

問題不在您發佈的代碼中。我將它複製到一個新的項目,它編譯沒有錯誤和警告 –

回答

5

我認爲這是Xcode的一個愚蠢的問題我重新啓動應用程序幾次,它結束了工作。

+0

我不能相信這個答案解決,但重新啓動Xcode解決了我的問題。多謝兄弟。 – PhatHV

4

您應經常檢查您的代理這種方式,在調用一個方法之前,即使有需要的協議方法:

if(self.delegate != nil && [ self.delegate respondsToSelector: @selector(removeTab:) ] 
{ 
    /* Call delegate method... */ 
} 

即使所需的方法這樣做增加了額外的安全,因爲這檢查在運行時完成。
有人可能會忽略或禁用編譯器警告,或通過類型轉換愚弄編譯器。

例如:

UILabel * label  = [ [ UILabel alloc ] initWithFrame: CGRectZero ]; 
someTableView.delegate = (id <UITableViewDelegate>)label; 

此外,您可能需要使用performSelector的實際方法調用:

[ self.delegate performSelector: @selector(removeTab:) withObject: self ]; 
+6

有關我不明白爲什麼這應該是必要的方法被定義爲在協議中的要求。如果未實現所需的方法,編譯器將顯示警告。 –

+1

@Macmade在方法調用中更喜歡'performSelector'的理由是什麼? – zaph

+0

@fluchtpunkt這是一個額外的安全,所以你不依賴於編譯器設置。看看我的編輯,它解釋了運行時檢查的原因。 – Macmade

1

嘗試將delegate重命名爲其他人一樣delegateForTab

你的類Tab被繼承UIView,所以self.delegateself類也是UIView的子類。 UIView可能有其自己的委託(它從UIResponder繼承,並從NSObject深入),並且它沒有-(void)removeTab方法。只是我個人的猜測。
我的解決方法是將其重命名爲它(沒有找到答案,它是否可以分類)。

建議使用委託:你應該實現和其他視圖控制器使用delegate,而不是在聲明它的同一類。 :)

+0

不錯的做法,但UIView沒有委託。所以這不會不幸......:) – Macmade

+0

@Macmade,謝謝你的建議!我遇到過這個問題之前:我創建了一個繼承自UINavigationController的類,導致了相同的錯誤,我通過重命名'delegate'來解決它。剛纔我提到SDK,UIView沒有它的委託,這是正確的。 :)但是,它從'UIResponder'繼承,並從'NSObject'深處繼承。 'NSObject'有它的協議和委託。所以我認爲'[self.delegate removeTab:self];''self'只是一個NSObject。我不確定這是否是真正的原因。只是我個人的猜測。 :p – Kjuly

0

這個錯誤不是編譯器錯誤,不是嗎?因爲我的代碼在這裏沒有編譯錯誤。

因此,如果這是一個運行時錯誤,有你宣佈你的委託類<TabDelegateDataSource>這樣的:

@interface SomeClass : UIView <TabDelegateDataSource>

如果你這樣做了,編譯器應該如果您的實例方法不能是警告你被發現。

或者你也應該發佈你的委託類的代碼以獲取更多信息。

P.S.代表不應該是__strong。您最好使用__unsafe_unretained代替。

14

我現在可以隨意重新創建並修復此錯誤。

確保.H頭在那裏,這是定義...

@protocol TabDelegateDataSource <NSObject> 
-(void)removeTab:(Tab *)tab; 
@end 

...包括無論您打算如何使用代表,例如在.M源的頂部,包括這個地方:

[self.delegate removeTab:self] 

如果編譯器只看到TabDelegateDataSource的向前定義這樣的:

@protocol TabDelegateDataSource; 

你會得到錯誤:

error: no known instance method for selector 'removeTab:' 

,而不是更多的預想前進定義相關的錯誤

+1

這是我的問題。我沒有在這個.h文件中導入我的協議的頭文件。謝謝你,先生 ! –

0

我導入我的appdelegate.h並解決錯誤...

2

請確保您沒有錯誤地在接口中聲明委託屬性(可能是通過複製並粘貼另一個文件)。例如:

@protocol SomeDelegate 

... 

@end 

@interface SomeClass 

... 

@property (nonatomic, retain) id<DifferentDelegate>delegate; 


@end 

上面一行將導致「爲選擇沒有已知實例的方法......」因爲與indtended協議,可能是複製和粘貼錯誤不匹配。此外,它可能會覆蓋來自實際所屬的不同類的正確引用,遠離這一行代碼,因此很難發現。

糾正上述與預期協議,宣佈你的財產:

@property (nonatomic, retain) id<SomeDelegate>delegate; 
+0

代表應該總是很弱(從不保留/強大) – SamB

0

有人可能會需要,

SEL selector = NSSelectorFromString(@"removeTab"); 

if([self.delegate respondsToSelector:selector]) { 
    objc_msgSend(self.delegate, selector); 
} 

注意:不要忘記這一點,#import <objc/message.h>

相關問題