2012-04-04 10 views
67

Qual è la differenza tra queste due dichiarazioni di classe? Non capisco perché @class è utilizzato qui. Grazie.Objective-C: direttiva @class prima di @interface?

@class TestClass; 

@interface TestClass: UIView { 
    UIImage *image1; 
    UIImage *image2; 
} 

e

@interface TestClass: UIView { 
    UIImage *image1; 
    UIImage *image2; 
} 

risposta

165

@class esiste per interrompere le dipendenze circolari. Di 'che hai le classi A e B.

@interface A:NSObject 
- (B*)calculateMyBNess; 
@end 

@interface B:NSObject 
- (A*)calculateMyANess; 
@end 

Pollo; incontrare Egg. Questo non può mai essere compilato perché l'interfaccia di A dipende dalla definizione di B e viceversa.

Quindi, può essere fissato con @class:

@class B; 
@interface A:NSObject 
- (B*)calculateMyBNess; 
@end 

@interface B:NSObject 
- (A*)calculateMyANess; 
@end 

@class dice efficacemente il compilatore che esiste in qualche luogo e, in tal modo, i puntatori dichiarati per puntare a istanze di detta classe sono perfettamente valide tale classe. Tuttavia, non è possibile chiamare un metodo su un riferimento di istanza il cui tipo è definito solo come @class perché non sono disponibili metadati aggiuntivi per il compilatore (non mi ricordo se restituisce il sito di chiamata a essere valutato come una chiamata attraverso id oppure no).

Nel tuo esempio, @class è innocuo, ma del tutto inutile.

+17

Vorrei poter dare un altro +1 solo per "chicken, meet egg" – lukya

+4

BTW, restituisce la valutazione 'id'. – jheld

+0

Ci sono motivi particolari per cui alcuni individui mettono '@ class' nel loro file .h e poi importano i file di intestazione necessari nel loro file .m, e altri potrebbero semplicemente importare il file .h nel file di intestazione delle classi corrente? Solo curioso, grazie. @bbum –

15
@class TestClass; 

Questo dichiara semplicemente "classe TestClass saranno definiti".

In questo caso (quello incollato) questo non ha alcun effetto, quindi sono gli stessi.

Tuttavia, nel caso in cui si definisca un protocollo che utilizzi il nome della classe (come tipo di parametri passati a delegare, ad esempio), sarà necessario dichiarare @class TestClass prima della definizione del protocollo, poiché la classe è ancora non definito.

In generale, se avete bisogno di indicare il vostro nome della classe prima della definizione di classe è fatto, è necessario rilasciare @class dichiarazione prima

+0

Ho visto questa implementazione il più prima dei protocolli. grazie per la condivisione! – SleepsOnNewspapers

6

Come per la risposta di Matt non c'è assolutamente nessun punto alla dichiarazione @class nel codice. @class forward definisce una classe in modo che il compilatore sappia in seguito a quale tipo di unità generale si sta riferendo. Poiché Objective-C è praticamente privo di funzioni in fase di esecuzione, è spesso tutto ciò che il compilatore deve effettivamente conoscere, quanto basta per distinguere la cosa da un valore C atomico.

Ho intenzione di fare una pugnalata al buio e di dire che poiché le variabili di istanza sono dichiarate nello @interface stai guardando un vecchio codice. Dato che si tratta di un vecchio codice, probabilmente lo @class era da qualche altra parte (ad esempio, c'era un protocollo delegato dichiarato in mezzo) e si è appena finito inoffensivo.

1

@class è molto utile quando è necessario definire un protocollo per un oggetto che di solito interagisce con l'oggetto di cui si sta definendo anche l'interfaccia. Usando @class, puoi mantenere la definizione del protocollo nell'intestazione della tua classe. Questo schema di delega viene spesso utilizzato su Objective-C ed è spesso preferibile alla definizione di "MyClass.h" e "MyClassDelegate.h".Questo può causare alcuni problemi di importazione di confusione

@class MyClass; 

@protocol MyClassDelegate<NSObject> 

- (void)myClassDidSomething:(MyClass *)myClass 
- (void)myClass:(MyClass *)myClass didSomethingWithResponse:(NSObject *)reponse 
- (BOOL)shouldMyClassDoSomething:(MyClass *)myClass; 
- (BOOL)shouldMyClass:(MyClass *)myClass doSomethingWithInput:(NSObject *)input 

@end 

@interface MyClass : NSObject 

@property (nonatomic, assign) id<MyClassDelegate> delegate; 

- (void)doSomething; 
- (void)doSomethingWithInput:(NSObject *)input 

@end 

Poi, quando si utilizza la classe, è possibile sia creare istanze della classe, nonché l'attuazione del protocollo con una singola istruzione import

#import "MyClass.h" 

@interface MyOtherClass()<MyClassDelegate> 

@property (nonatomic, strong) MyClass *myClass; 

@end 

@implementation MyOtherClass 

#pragma mark - MyClassDelegate Protocol Methods 

- (void)myClassDidSomething:(MyClass *)myClass { 

    NSLog(@"My Class Did Something!") 

} 

- (void)myClassDidSomethingWithResponse:(NSObject *)response { 

    NSLog(@"My Class Did Something With %@", response); 

} 

- (BOOL)shouldMyClassDoSomething { 

    return YES; 

- (BOOL)shouldMyClassDoSomethingWithInput:(NSObject *)input { 

    if ([input isEqual:@YES]) { 

     return YES; 

    } 

    return NO; 

} 


- (void)doSomething { 

    self.myClass = [[MyClass alloc] init]; 
    self.myClass.delegate = self; 
    [self.myClass doSomething]; 
    [self.myClass doSomethingWithInput:@0]; 

} 
Problemi correlati