Enum de déclaration en avant dans Objective-C

J’ai de la difficulté avec la visibilité enum dans un programme Objective-C. J’ai deux fichiers d’en-tête et un définit un typedef enum . Un autre fichier doit utiliser le type typedef ‘d.

Dans straight C, je voudrais simplement #include l’autre fichier d’en-tête, mais dans Objective-C, il est recommandé de ne pas utiliser #import entre les fichiers d’en-tête, en utilisant plutôt les déclarations @class avancées si nécessaire. Cependant, je n’arrive pas à comprendre comment faire une déclaration anticipée d’un type d’énumération.

Je n’ai pas besoin des valeurs énumérées réelles, sauf dans le fichier d’implémentation .m correspondant, où je peux .m toute sécurité. Alors, comment puis-je que le typedef enum soit reconnu dans l’en-tête?

Allez-y et utilisez #import . La seule raison pour laquelle les gens recommandent d’utiliser @class lorsque cela est possible est que cela rend votre code légèrement plus rapide à comstackr. Cependant, il n’y a pas de problème avec #import un fichier .h d’un autre. En fait, vous devez le faire lors de l’extension d’une autre classe.

La manière la plus récente (Swift 3; mai 2017) de déclarer le enum (NS_ENUM / NS_OPTION) dans objective-c consiste à utiliser ce qui suit:

 // Forward declaration for XYZCharacterType in other header say XYZCharacter.h typedef NS_ENUM(NSUInteger, XYZCharacterType); // Enum declaration header: "XYZEnumType.h" #ifndef XYZCharacterType_h #define XYZCharacterType_h typedef NS_ENUM(NSUInteger, XYZEnumType) { XYZCharacterTypeNotSet, XYZCharacterTypeAgent, XYZCharacterTypeKiller, }; #endif /* XYZCharacterType_h */` 

La réponse à votre question consiste à importer le fichier d’en-tête typedef ou à utiliser un type générique tel que NSInteger au lieu du type enum.

Cependant, il y a plus de raisons de ne pas importer de fichier d’en-tête que de comstackr rapidement.

Ne pas importer un fichier d’en-tête réduit également votre access par inadvertance aux classes superflues.

Par exemple, supposons que vous ayez une classe TrackFileChanges qui effectue le suivi du système de fichiers pour les modifications apscopes à un fichier spécifique et que vous avez une classe CachedFile qui stocke les données mises en cache à partir d’un fichier. Ce dernier pourrait utiliser un ivar privé de type TrackFileChanges *, mais pour les utilisations de CachedFile, il s’agit simplement d’un détail d’implémentation (idéalement, l’ivar serait généré automatiquement avec une propriété privée utilisant le nouveau runtime, mais ce n’est pas possible). utiliser l’ancien temps d’exécution).

Donc, les clients qui #import “CachedFile.h” n’ont probablement pas besoin ou veulent accéder à TrackFileChanges.h. Et s’ils le font, ils devraient le faire savoir en l’important eux-mêmes. En utilisant @class TrackFileChanges instea de #import “TrackFileChanges.h” dans CachedFile.h, vous améliorez l’encapsulation.

Mais tout cela dit, il n’ya rien d’important à importer un fichier d’en-tête à partir d’un second fichier d’en-tête si le second en-tête veut exposer le premier à tous les clients. Par exemple, les fichiers d’en-tête qui déclarent des classes doivent être importés directement dans des fichiers d’en-tête de sous-classement, et les fichiers d’en-tête déclarant des protocoles peuvent être directement importés (bien que vous puissiez utiliser @ protocole ABC pour éviter cela).

Si vous utilisez bien les extensions du compilateur, vous pouvez utiliser cet ordre dans Clang:

 enum Enum; typedef enum Enum Enum2; void f(Enum2); // ok. it sees this type's true name. enum Enum { E_1 }; // ok. now its declaration is visible and we can use it. void f(Enum2 e) { } 

Remarque: Cela déclenchera un avertissement de type -Wpedantic .


Si vous utilisez C ++ 11, vous devez utiliser leurs enum class Enum:uint8_t; , que vous pouvez transférer en toute sécurité dans la déclaration – par exemple, la enum class Enum:uint8_t; (pas une extension du compilateur).

Ce qui a fonctionné pour une déclaration en avant d’un enum pour moi dans un fichier Objective C .h était regarder dans le fichier ProjectName-Swift.h et voir ce qu’il a mis, qui se trouve être le suivant:

enum SwiftEnumName: NSInteger;

J’avais besoin de cette déclaration anticipée car j’avais un type de paramètre de fonction SwiftEnumName. Et cela ne me laisserait pas mettre l’importation ProjectName-Swift.h dans le fichier Objective C .h.

Ensuite, dans le fichier Objective C .m, je viens juste d’avoir le #import “ProjectName-Swift.h” et j’ai simplement utilisé le SwiftEnum normalement.

Cela utilisait Swift 4.1.2.

Vous devrez soit les #import de toute façon, soit créer un fichier d’en-tête distinct contenant uniquement le typedef . Ne pas importer de fichiers d’en-tête dans un en-tête rend la compilation plus rapide, mais ne change rien d’autre.

Pourquoi C ++ ne prend-il pas en charge la déclaration en avant des énumérations?