web-dev-qa-db-fra.com

Objectif-C: directive @class avant @interface?

Quelle est la différence entre ces deux déclarations de classe? Je ne comprends pas pourquoi @class est utilisé ici. Merci.

@class TestClass;

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

et

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

@class existe pour rompre les dépendances circulaires. Disons que vous avez les classes A et B.

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

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

Poulet; rencontrer Egg. Cela ne peut jamais être compilé car l'interface de A dépend de la définition de B et vice versa.

Ainsi, il peut être corrigé en utilisant @class:

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

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

@class indique effectivement au compilateur qu'une telle classe existe quelque part et, par conséquent, les pointeurs déclarés pour pointer vers des instances de ladite classe sont parfaitement valides. Cependant, vous ne pouvez pas appeler une méthode sur une référence d'instance dont le type est uniquement défini en tant que @class car il n'y a pas de métadonnées supplémentaires disponibles pour le compilateur (je ne me souviens pas s'il rétablit le site d'appel à être évalué en tant qu'appel via id ou non).

Dans votre exemple, le @class est inoffensif, mais totalement inutile.

182
bbum
@class TestClass;

Cela déclare simplement que "la classe TestClass sera définie".

Dans ce cas (celui que vous avez collé), cela n'a aucun effet, donc ce sont les mêmes.

Cependant, dans le cas où vous allez définir un protocole qui utiliserait votre nom de classe (comme type de paramètres passés à déléguer, par exemple), vous devrez déclarer @class TestClass avant la définition du protocole, car votre classe n'est toujours pas définie.

En général, si vous devez mentionner le nom de votre classe avant la définition de la classe, vous devrez émettre @class déclaration d'abord

18
poncha

Selon la réponse de Matt, il n'y a absolument aucun intérêt au @class déclaration dans votre code. @class forward définit une classe afin que le compilateur sache par la suite à quel type général d'unité vous faites référence. Étant donné qu'Objective-C est à peu près sans type à l'exécution, c'est souvent tout ce que le compilateur doit réellement savoir - juste assez pour distinguer la chose d'une valeur atomique en C.

Je vais essayer dans le noir et dire que parce que les variables d'instance sont déclarées dans le @interface vous regardez un vieux code. Parce que c'est de l'ancien code, le @class était probablement ailleurs (par exemple, un protocole délégué a été déclaré entre les deux) et vient de se retrouver échoué sans danger.

6
Tommy

@class est assez pratique lorsque vous devez définir un protocole pour un objet qui interagira généralement avec l'objet dont vous définissez également l'interface. En utilisant @class, vous pouvez conserver la définition de protocole dans l'en-tête de votre classe. Ce modèle de délégation est souvent utilisé sur Objective-C et est souvent préférable à la définition de "MyClass.h" et "MyClassDelegate.h". Cela peut entraîner des problèmes d'importation déroutants

@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

Ensuite, lorsque vous utilisez la classe, vous pouvez à la fois créer des instances de la classe et implémenter le protocole avec une seule instruction d'importation

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

}
3
vsanthanam510