2011-11-12 10 views
40

Ho tentato di compilare, ma ogni volta che lo faccio, un metodo genera uno strano errore "previsto di tipo". Ho un metodo nell'intestazione:Errore "un tipo previsto" che punta al tipo restituito di un metodo

-(ANObject *)generateSomethingForSomethingElse:(NSString *)somethingElse; 

I punti di errore nel tipo di ritorno per questo metodo. Ho importato ANObject nell'intestazione usando #import "ANObject.h" e ANObject sto compilando bene ..

Perché sta succedendo?

+0

sembra andare bene .. puoi pubblicare una parte del tuo codice? – Devarshi

+0

anche ... è una parte ANObject di qualche altro framework? – Devarshi

+4

Modifica la tua domanda per includere sia il contenuto di ANObject.h che l'intestazione che ti dà il problema. E per favore mostra il tuo codice attuale, non il codice inventato che potrebbe non includere il problema. –

risposta

89

Ciò è a che fare con l'ordine in cui i file di origine vengono compilati in Siete già probabilmente consapevoli del fatto che non si può chiamare un metodo prima che venga definita (vedi sotto pseudocodice):

var value = someMethod(); 

function someMethod() 
{ 
    ... 
} 

Questo causerebbe un errore in fase di compilazione poiché someMethod() non è stato ancora definito. Lo stesso vale per le classi. Le classi sono compilate una dopo l'altra dal compilatore.

Quindi, se si immagina che tutte le classi vengano inserite in un file gigante prima della compilazione, è possibile visualizzare il problema. Guardiamo la classe Ship e BoatYard:

@interface BoatYard : NSObject 
@property (nonatomic, retain) Ship* currentShip; 
@end 

@interface Ship : NSObject 
@property (nonatomic, retain) NSString* name; 
@property (nonatomic, assign) float weight; 
@end 

Ancora una volta, perché la classe Ship non è stato ancora definito, non possiamo fare riferimento ad esso ancora. Risolvere questo particolare problema è piuttosto semplice; cambia l'ordine di compilazione e compila. Sono sicuro che sei familliar con questa schermata in XCode:

Ma siete consapevoli che è possibile trascinare i file su e giù nella lista? Ciò cambia l'ordine in cui i file verranno compilati. Pertanto, sposta semplicemente la classe Ship sopra la classe BoatYard e tutto è buono.

Ma, cosa succede se non si vuole farlo, o, soprattutto, cosa succede se c'è una relazione circolare tra i due oggetti? Aumentiamo la complessità di quel diagramma di oggetto con l'aggiunta di un riferimento alla corrente BoatYard che il Ship è in:

@interface BoatYard : NSObject 
@property (nonatomic, retain) Ship* currentShip; 
@end 

@interface Ship : NSObject 
@property (nonatomic, retain) BoatYard* currentBoatYard; 
@property (nonatomic, retain) NSString* name; 
@property (nonatomic, assign) float weight; 
@end 

Oh cara, ora abbiamo un problema. Questi due non possono essere compilati fianco a fianco. Abbiamo bisogno di un modo per informare il compilatore che la classe Ship * esiste realmente. Ed è per questo che la parola chiave @class è così a portata di mano.

Per dirla in parole povere, stai dicendo: "Fidati di me, lo Ship esiste davvero e lo vedrai molto presto". Per mettere tutto insieme:

@class Ship; 

@interface BoatYard : NSObject 
@property (nonatomic, retain) Ship* currentShip; 
@end 

@interface Ship : NSObject 
@property (nonatomic, retain) BoatYard* currentBoatYard; 
@property (nonatomic, retain) NSString* name; 
@property (nonatomic, assign) float weight; 
@end 

Ora il compilatore sa come si compila BoatYard, che apparirà presto una definizione Ship di classe. Ovviamente, se così non fosse, la compilazione riuscirà comunque.

Tutta la parola chiave @class tuttavia informa il compilatore che la classe arriverà presto. È non un sostituto per #import.È comunque necessario importare il file di intestazione, altrimenti non sarà possibile accedere ad uno qualsiasi degli interni di classe:

@class Ship 

-(void) example 
{ 
    Ship* newShip = [[Ship alloc] init]; 
} 

Questo non può funzionare, e non riuscirà con un messaggio di errore dicendo che la nave è una dichiarazione in avanti. Una volta che hai #import "Ship.h", allora sarai in grado di creare l'istanza dell'oggetto.

+0

Steve, puoi spiegare il motivo per cui ciò accade? evviva – theiOSDude

+2

@ burrows111: Dopo la riflessione, questa è una risposta piuttosto pigra; Devo aver avuto fretta quando l'ho scritto. Le altre risposte spiegano come risolverlo, ma non riesco a vederne una che spieghi perché accade. Spero che la risposta modificata ti aiuti. –

+0

ha molto più senso! salute, amico! – theiOSDude

1

Di solito quando vedo un errore come questo è perché ho un errore di battitura su una riga precedente, ad esempio una parentesi aggiuntiva o mancante o qualcosa del genere. .

52

Ho trovato che questo errore si verifica quando c'è una dipendenza circolare sulle intestazioni. Controllare se il file .h in cui si dichiara questo metodo viene importato in ANObject.h

+2

Sì, ricevevo un errore simile a causa della dipendenza circolare. Evitarlo includendo la dichiarazione di classe forward nel file di interfaccia e l'importazione del file di intestazione nell'implementazione. –

+0

Questo funziona meglio per me :), grazie! – mm24

22

Che, fondamentalmente, aggiungere

@class ANObject; 

prima @interface!

+0

non so come ma questo ha risolto il mio problema. #import non funziona e @class funziona .. – dreampowder

+0

Bene che funzioni per te :) Sempre felice di aiutare – JomanJi

1

Ho ricevuto questo messaggio, quando il tipo di variabile era errato. Vedi sotto questo sotto

ad es.

-(void)takeSimulatorSafePhotoWithPopoverFrame:(GCRect)popoverFrame { 

invece di .....

-(void)takeSimulatorSafePhotoWithPopoverFrame:(CGRect)popoverFrame { 
+3

Mi ci è voluto abbastanza tempo per capire che la differenza è CGRect e GCRect. – OlivaresF

4

Così, per qualche ragione mi è stato sempre questo errore durante il tentativo di impostare un metodo con un tipo enum nei parametri. In questo modo:

- (void)foo:(MyEnumVariable)enumVariable; 

avevo usato in precedenza in questo modo e mai avuto un problema, ma ora l'ho fatto. Ho controllato la dipendenza circolare e non ho trovato nessuno. Ho anche controllato gli errori di battitura più volte e nessun dado. Ciò che ha finito per risolvere il mio problema è stato aggiungere "enum" prima di voler accedere alla variabile. In questo modo:

- (void)foo:(enum MyEnumVariable)enumVariable; 
{ 
    enum MyEnumVariable anotherEnumVariable; 
} 
1

Può sembrare stupido, ma bombardamento sbagliato o errato utilizzo caso letterwrong maiuscole/minuscole questo.

+0

Odio quei casi di lettere! – DiscDev

0

Stranamente, la modifica dell'ordine delle mie importazioni ha risolto il problema in passato ... Provare a spostare l'importazione verso il basso dopo tutte le altre importazioni.

Problemi correlati