2011-12-05 6 views
12

Ho bisogno di aiuto per il debug della mia classe. Sto ottenendo un errore talmente bizzarro da non riuscire a trovare nulla di simile, quindi metto giù la maggior parte del mio codice.Errore Xcode: nessun metodo di istanza noto per il selettore

//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

Per curiosità, cosa accadrebbe se sostituissi 'self.delegate' con' _delegate' sulla riga incriminata? – dasblinkenlight

+0

Il tuo delegato ha effettivamente un metodo 'removeTab'? Questo messaggio di errore implica che non lo sia. Prova a eseguire il debug e ispezionare self.delegate e assicurati che sia quello che ti aspetti e che abbia un metodo 'removeTab'. – WilHall

+1

il problema non è nel codice che hai postato. L'ho copiato in un nuovo progetto e viene compilato senza errori e avvisi –

risposta

5

Penso che sia stato uno stupido problema con Xcode Ho riavviato l'app un paio di volte e ha finito per funzionare.

+0

Non riesco a credere che questa risposta funzioni, ma riavviare Xcode ha risolto il mio problema. Grazie fratello. – PhatHV

4

Si dovrebbe sempre controllare il delegato in questo modo, prima di chiamare un metodo, anche con metodi di protocollo necessari:

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

In questo modo, anche per i metodi richiesti aggiunge un extra di sicurezza, in quanto questo controllo è fatto in fase di esecuzione.
Qualcuno può ignorare o disabilitare gli avvisi del compilatore o ingannare il compilatore con i cast di tipo.

Per esempio:

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

Inoltre, si consiglia di utilizzare performSelector per la chiamata al metodo attuale:

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

Non vedo perché questo dovrebbe essere necessario per i metodi definiti come richiesti nel protocollo. Il compilatore mostrerà un avviso se non è implementato un metodo richiesto. –

+1

@Macmade Qual è il criterio per preferire 'performSelector' a una chiamata di metodo? – zaph

+0

@fluchtpunkt Questa è una sicurezza extra, quindi non fare affidamento sulle impostazioni del compilatore. Vedi la mia modifica, che spiega il motivo del controllo runtime. – Macmade

1

Provare a rinominare il delegate ad altri come delegateForTab.

La classe Tab è sottoclasse UIView, così self.delegate s' self classe è anche una sottoclasse della UIView. UIView may ha il proprio delegato (eredita da UIResponder e profondo da NSObject) e non ha il metodo -(void)removeTab. Solo la mia ipotesi personale.
La mia soluzione è rinominare (non trovare la risposta se può essere già sottoclasse).

Suggerimento per l'utilizzo di delegato: Si dovrebbe implementare il e utilizzare il delegate in altri controller di vista, non nella stessa classe che si dichiara. :)

+0

Buone pratiche, ma UIView non ha un delegato. Quindi questo non aiuta purtroppo ...:) – Macmade

+0

@Macmade, grazie per il tuo consiglio!Ho già incontrato questo problema prima: ho creato una classe che eredita da UINavigationController, risultante con lo stesso errore, e l'ho risolta rinominando il 'delegato'. Proprio ora, mi riferisco all'SDK, l'UIView non ha il suo delegato, è giusto. :) Tuttavia, eredita da 'UIResponder', e in profondità da' NSObject'. 'NSObject' ha il suo protocollo e il suo delegato. Quindi penso '[self.delegate removeTab: self];' 's' self' è solo un NSObject. Non sono sicuro che questa sia una vera ragione. Solo la mia ipotesi personale. : p – Kjuly

0

Questo errore non è un errore del compilatore, non è vero? Perché non ho errori di compilazione con il tuo codice qui.

Quindi, se si tratta di un errore di runtime, avete dichiarato <TabDelegateDataSource> nelle classi delegato in questo modo:

@interface SomeClass : UIView <TabDelegateDataSource>

Se avete fatto così, il compilatore dovrebbe essere che avvisa se il vostro metodo di istanza non può Essere trovato.

O forse dovresti anche inserire il codice della tua classe di delegato per ulteriori informazioni.

P.S. Il delegato non dovrebbe essere __strong. Faresti meglio a usare __unsafe_unretained invece.

14

Ora riesco a ricreare e correggere questo errore a piacimento.

Assicurarsi che l'intestazione .h, ove definita ...

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

...è incluso ovunque tu intenda utilizzare il delegato, ad es. da qualche parte in alto della fonte .m che include questo:

[self.delegate removeTab:self] 

Se il compilatore ha visto solo un attaccante definizione di TabDelegateDataSource come questo:

@protocol TabDelegateDataSource; 

si otterrà l'errore:

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

e non l'errore relativo più attesi in avanti definizione

+1

Questo era il mio problema. Non stavo importando l'intestazione per il mio protocollo in questo file .h. Grazie Signore ! I delegati –

0

Importazione mia appdelegate.h e errore risolto ...

2

Assicurarsi di non aver dichiarato in modo errato la proprietà del delegato nell'interfaccia (probabilmente copiando e incollando da un altro file). Per esempio:

@protocol SomeDelegate 

... 

@end 

@interface SomeClass 

... 

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


@end 

La linea di cui sopra farà sì che il "No metodo di istanza conosciuta per il selettore ..." a causa della mancata corrispondenza con il protocollo indtended, probabilmente un errore di copia e incolla. Inoltre, è probabile che sovrascriva il corretto riferimento a da una classe DIVERSA in cui effettivamente appartiene, lontano da questa linea di codice, rendendolo difficile da individuare.

Correggere quanto sopra dichiarando la vostra proprietà con il protocollo previsto:

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

devono sempre essere deboli (mai conservare/forti) – SamB

0

Qualcuno potrebbe necessario,

SEL selector = NSSelectorFromString(@"removeTab"); 

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

Nota: Non dimenticare questo, #import <objc/message.h>

Problemi correlati