web-dev-qa-db-fra.com

Quel est le meilleur moyen de créer des constantes dans Objective-C?

Je crée un client Reddit à des fins d'apprentissage. J'ai besoin d'un fichier avec des constantes. Je pensais à importer le fichier dans le fichier Reddit-Prefix.pch afin de rendre les constantes disponibles pour tous les fichiers. Est-ce une bonne façon de faire les choses? De plus, j'ai fait mes recherches et découvert plusieurs méthodes pour créer des constantes, mais je ne sais pas laquelle utiliser:

  • Macro #define
  • const
  • static const
  • extern const
  • enum

Quel est le chemin préféré? Quelle est la convention? Je sais que "ça dépend", mais ma question est plus précisément: Quels sont les cas d'utilisation de chacune de ces solutions?

De plus, si vous utilisez extern const, dois-je importer le fichier ou les constantes seront disponibles globalement sans importer le fichier?

Une chose que je pourrais logiquement conclure est que enum est le meilleur choix pour définir quelque chose comme des domaines d'erreur personnalisés (suis-je en fait vrai?). Mais qu'en est-il des autres?

154
Robert Audi

La première question est de savoir quelle étendue vous souhaitez que vos constantes aient, ce qui est en fait deux questions:

  • Ces constantes sont-elles spécifiques à une seule classe ou est-il judicieux de les avoir partout dans l'application?
  • S'ils sont spécifiques à une classe, sont-ils destinés à être utilisés par les clients de la classe ou uniquement au sein de la classe?

S'ils sont spécifiques et internes à une seule classe, déclarez-les en tant que static const en haut du fichier .m, comme suit:

static NSString *const MyThingNotificationKey = @"MyThingNotificationKey";

Si elles appartiennent à une seule classe mais qu'elles doivent être publiques/utilisées par d'autres classes, déclarez-les en tant que extern dans l'en-tête et définissez-les dans le fichier .m:

//.h
extern NSString *const MyThingNotificationKey;

//.m
NSString *const MyThingNotificationKey = @"MyThingNotificationKey";

Si elles doivent être globales, déclarez-les dans un en-tête et définissez-les dans un module correspondant, en particulier pour ces constantes.

Vous pouvez les combiner pour différentes constantes avec différents niveaux de global, et pour différentes constantes globales qui ne se ressemblent tout simplement pas. Vous pouvez les placer dans des modules séparés, chacun avec son propre en-tête, si vous le souhaitez. vouloir.

Pourquoi pas #define?

L'ancienne réponse était "Les macros n'ont pas d'informations de type", mais aujourd'hui, les compilateurs sont assez intelligents pour effectuer toute la vérification de type des littéraux (à quoi les macros se développent) ainsi que des variables.

La réponse moderne est que le débogueur ne saura rien de vos macros. Vous ne pouvez pas dire [myThing addObserver:self forKey:MyThingNotificationKey] dans une commande de débogage si MyThingNotificationKey est une macro; le débogueur ne peut le savoir que s'il s'agit d'une variable.

Pourquoi pas enum?

Eh bien, rmaddy m'a battu dans les commentaires: enum ne peut définir que des constantes entières. Des choses comme les numéros d’identifiant de série, les masques binaires, les codes à quatre octets, etc.

Pour ces raisons, enum est génial et vous devez absolument l'utiliser. (Encore mieux, utilisez les macros NS_ENUM et NS_OPTIONS _ .) Pour les autres tâches, vous devez utiliser autre chose; enum ne fait que des entiers.

Et d'autres questions

Je pensais à importer le fichier dans le fichier Reddit-Prefix.pch pour que les constantes soient disponibles pour tous les fichiers. Est-ce une bonne façon de faire les choses?

Probablement inoffensif, mais probablement excessif. Importez vos en-têtes de constantes là où vous en avez besoin.

Quels sont les cas d'utilisation pour chacune de ces solutions?

  • #define: Assez limité. Honnêtement, je ne suis pas sûr qu'il y ait une bonne raison d'utiliser cela pour les constantes.
  • const: Idéal pour les constantes locales. En outre, vous devez utiliser ceci pour celui que vous avez déclaré dans un en-tête et que vous définissez maintenant.
  • static const: Idéal pour les constantes spécifiques à un fichier (ou à une classe).
  • extern const: Vous devez l'utiliser pour exporter une constante dans un en-tête.

De plus, si vous utilisez extern const, dois-je importer le fichier ou les constantes seront disponibles globalement sans importer le fichier?

Vous devez importer le fichier, dans chaque fichier où vous l'utilisez ou dans l'en-tête du préfixe.

384
Peter Hosey

FOUNDATION_EXPORT

Pensez à utiliser FOUNDATION_EXPORT pour un peu plus de compatibilité que extern puisqu'il est défini dans la base et compile dans des formats compatibles pour C, C++ et Win32.

Comme défini dans NSObjCRuntime.h

#if defined(__cplusplus)
#define FOUNDATION_EXTERN extern "C"
#else
#define FOUNDATION_EXTERN extern
#endif

#if TARGET_OS_WIN32

    #if defined(NSBUILDINGFOUNDATION)
        #define FOUNDATION_EXPORT FOUNDATION_EXTERN __declspec(dllexport)
    #else
        #define FOUNDATION_EXPORT FOUNDATION_EXTERN __declspec(dllimport)
    #endif

    #define FOUNDATION_IMPORT FOUNDATION_EXTERN __declspec(dllimport)

#else
    #define FOUNDATION_EXPORT  FOUNDATION_EXTERN
    #define FOUNDATION_IMPORT FOUNDATION_EXTERN
#endif
8
Steve Moser