Objective-C: @class Directive before @interface?
@class TestClass;
@interface TestClass: UIView {
UIImage *image1;
UIImage *image2;
}
e
@interface TestClass: UIView {
UIImage *image1;
UIImage *image2;
}
4 answers
@class
existe para quebrar as dependências circulares. Digamos que tens aulas A E B.
@interface A:NSObject
- (B*)calculateMyBNess;
@end
@interface B:NSObject
- (A*)calculateMyANess;
@end
Galinha, apresento-te o Egg. Isso nunca pode compilar porque a interface de A Depende de B ser definido e vice-versa.
Assim, pode ser corrigido usando @class
:
@class B;
@interface A:NSObject
- (B*)calculateMyBNess;
@end
@interface B:NSObject
- (A*)calculateMyANess;
@end
@class
efetivamente diz ao compilador que tal classe existe em algum lugar e, portanto, ponteiros declarados para apontar para instâncias dessa classe são perfeitamente válidos. No entanto, você não poderia chamar um método em uma instância referência cujo tipo é definido como um @class
porque não há nenhuma metadados adicionais disponíveis para o compilador (não lembro se ele reverte o site de chamada para ser avaliado como uma chamada através id
ou não).
@class
é inofensivo, mas totalmente desnecessário.
@class TestClass;
Isto apenas declara "classe TestClass será definida".
Neste caso (aquele que colaste) isto não tem qualquer efeito, por isso estes são os mesmos.No entanto, no caso de ir definir um protocolo que usaria o nome da sua classe (como tipo de parâmetros passados para delegar, por exemplo), terá de declarar @class TestClass
antes da definição do protocolo, dado que a sua classe ainda não está definida.
Em geral, se precisar de mencionar o nome da sua classe antes do a definição da classe é feita, você terá que emitir a Declaração @class
primeiro
@class é bastante útil quando você precisa definir um protocolo para um objeto que normalmente irá interagir com o objeto cuja interface você também está definindo. Usando @class, você pode manter a definição do protocolo no cabeçalho de sua classe. Este padrão de delegação é muitas vezes usado no Objetivo-C, e é muitas vezes preferível a definir ambos "MyClass.h " E " MyClass delegate.h". Isso pode causar problemas de importação confusos.
@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
// MyClass hasn't been defined yet, but MyClassDelegate will still compile even tho
// params mention MyClass, because of the @class declaration.
// You're telling the compiler "it's coming. don't worry".
// You can't send MyClass any messages (you can't send messages in a protocol declaration anyway),
// but it's important to note that @class only lets you reference the yet-to-be-defined class. That's all.
// The compiler doesn't know anything about MyClass other than its definition is coming eventually.
@interface MyClass : NSObject
@property (nonatomic, assign) id<MyClassDelegate> delegate;
- (void)doSomething;
- (void)doSomethingWithInput:(NSObject *)input
@end
Então, quando você está usando a classe, você pode criar instâncias da classe, bem como implementar o protocolo com uma única declaração de importação
#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];
}