Objective-C: @class Directive before @interface?

Qual é a diferença entre estas duas declarações de classe? Não entendo porque é que a classe @é utilizada aqui. Obrigado.

@class TestClass;

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

e

@interface TestClass: UIView {
    UIImage *image1;
    UIImage *image2;
}
Author: Ryan, 2012-04-04

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).

No seu exemplo, o @class é inofensivo, mas totalmente desnecessário.
 196
Author: bbum, 2012-04-04 22:22:40
@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

 18
Author: poncha, 2012-04-04 22:17:00
De acordo com a resposta do Matt, não faz sentido a declaração no seu código. {[[0]} forward define uma classe para que o compilador saiba subsequentemente a que tipo geral de unidade se refere. Uma vez que o Objective-C é praticamente sem digitação em tempo de execução, isso é muitas vezes tudo o que o compilador realmente precisa saber - apenas o suficiente para distinguir a coisa de um valor atômico C. Vou dar uma facada no escuro e dizer que porque as variáveis de instância são declaradas no {[2] você está olhando para algum código antigo. Porque é um código antigo, o {[[0]} provavelmente costumava estar em outro lugar (por exemplo, havia um protocolo de delegado declarado no meio) e acabou por ficar inutilmente encalhado.
 7
Author: Tommy, 2012-04-04 22:17:52

@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];

}
 4
Author: vsanthanam510, 2019-01-04 19:48:38