57 votes

Déclarations à terme du protocole Objective-C

ObjectProperties.h

@protocol ObjectProperties <NSObject>

@property (strong, nonatomic) NSString *name;
@property (strong, nonatomic) NSDate *date;
@property (assign, nonatomic) int64_t index;

@end

ClassA.h

#import <Foundation/Foundation.h>

@protocol ObjectProperties;

@interface ClassA : NSObject <ObjectProperties>

- (void)specialSauce;

@end;

ManagedClassA.h

#import <CoreData/CoreData.h>

@protocol ObjectProperties;

@interface ManagedClassA : NSManagedObject <ObjectProperties>

- (void)doSomething;

@end;

À partir de l'exemple de code ci-dessus, j'ai défini un protocole dans un .h de fichier à utiliser avec la Base de Données des objets ainsi que la plaine ol' vanille objets. Il semble que le "bruit" d'avoir conformes classes #import du protocole dans l'en-tête; il serait plus propre de déclarer avant le protocole et les importer dans le fichier d'implémentation comme je l'ai indiqué ci-dessus. Cependant, Xcode, lance un avertissement lorsque le faisant de cette manière:

Cannot find protocol definition for 'ObjectProperties'

Le code compile, et la plupart des œuvres. Je dis la plupart car il y a certains funkiness avec Base de Données en essayant de créer dynamiquement les getters / setters pour la propriété scalaire, mais je pense que c'est probablement parce que j'ai frappé un cas limite.

Bien sûr, le plus évident de contourner ce problème consiste à il suffit d'importer l'en-tête de protocole dans la classe des en-têtes.

Si ma compréhension est correcte (et à ma connaissance est très récemment acquis, et il est donc tout à fait possible que je me trompe), si j'importe le protocole dans ma classe en-têtes et de faire un changement dans le protocole, puis tous les fichiers importer mes classes devront être recompilés.

Quelle est la façon correcte de faire de résoudre ce type de problème?

107voto

newacct Points 42530

Vous ne pouvez pas déclarer avant une super-classe ou d'un protocole qu'il est conforme. Dans ces cas, vous devez inclure l'en-tête. C'est parce que (dans le cas de la super-classe) de la super-classe des variables d'instance et les méthodes deviennent une partie de votre classe; ou (dans le cas des protocoles), le protocole de méthodes deviennent les méthodes déclarées dans votre classe, sans avoir à les déclarer explicitement. (c'est à dire aujourd'hui, d'autres personnes qui comprennent votre classe en-tête de votre classe déclare des méthodes, comme si vous avez déclaré vous-même.) La seule façon que cela pourrait être possible si elles ont été déjà définis dans le présent champ d'application, c'est à dire leurs têtes sont importés.

#import <SomeClass.h>
#import <SomeProtocol.h> // these two must be imported

@interface MyClass : SomeClass <SomeProtocol>
@end

Avant les déclarations sont utiles pour les choses qui viennent de se montrer dans le type d'une variable (plus précisément, un objet pointeur de variable). Pointeurs d'objet sont toutes de la même taille et il n'y a pas de différence entre les différents types de pointeurs d'objet au moment de l'exécution (la notion de type de pointeur d'objet est seulement au moment de la compilation chose). Donc, il n'y a pas de réel besoin de savoir exactement ce qui est dans les classes de ces types. Ainsi, ils peuvent être des avant-déclaré.

@class SomeClass;
@protocol SomeProtocol; // you can forward-declare these

@interface MyClass {
    SomeClass *var1;
    id<SomeProtocol> var2;
}
@end

4voto

borrrden Points 20950

Oui vous avez raison que tous les fichiers devront être recompilés, mais c'est nécessaire. Les fichiers importer la classe d'en-tête doivent connaître les méthodes associées avec le protocole, il met en œuvre. Si vous mettez de côté cette définition, loin de la .m fichier, il n'est visible que d'un seul fichier (depuis .m les fichiers ne jamais obtenir importé). Ce n'est pas la même qu'avant de déclarer des classes. Si vous déclarer avant un protocole, vous devez le déclarer quelque part qui est visible dans le même champ d'application que la déclaration anticipée. Je ne vois pas d'exemple où cela ne se produit pas dans le même fichier.

Dans l'ARC c'est une erreur, parce que l'ARC a besoin de savoir à propos de la gestion de la mémoire de l'déclaré méthodes (font-ils de retour +1 cas, pointeurs internes, etc?)

2voto

xingzhi.sg Points 221

En déclarant votre classe dans MyClass.h, vous devez importer tous les fichiers d'en-tête de sa superclasse ainsi que les protocoles adoptés dans le fichier MyClass.h. Les protocoles dans Objective-c sont considérés comme un type d'héritage variant.

Les déclarations en aval sont généralement utilisées dans la déclaration de membre de la classe.

1voto

Steven Fisher Points 22249

Puisque vous déclarez la conformité au protocole, vous devriez #importer l'en-tête contenant le protocole.

Cela revient à # importer une super-classe, plutôt que de la déclarer avant:

 @class Foo;

@interface Bar : Foo
// Will get error: attempting to use the forward class 'Foo' as superclass of 'Bar'
@end;
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X