Question Constantes en Objective-C


Je développe un Cacao application, et j'utilise constante NSStrings comme moyen de stocker les noms de clés pour mes préférences.

Je comprends que c'est une bonne idée, car cela permet de changer facilement de clés si nécessaire. De plus, c'est l'ensemble de la notion de «séparer vos données de votre logique».

Quoi qu'il en soit, existe-t-il un bon moyen de définir ces constantes une fois pour toute l'application? Je suis sûr qu'il y a un moyen facile et intelligent, mais en ce moment mes cours redéfinissent ceux qu'ils utilisent.


969
2018-02-11 21:52


origine


Réponses:


Vous devriez créer un fichier d'en-tête comme

// Constants.h
FOUNDATION_EXPORT NSString *const MyFirstConstant;
FOUNDATION_EXPORT NSString *const MySecondConstant;
//etc.

(vous pouvez utiliser extern au lieu de FOUNDATION_EXPORT si votre code ne sera pas utilisé dans des environnements mixtes C / C ++ ou sur d'autres plates-formes)

Vous pouvez inclure ce fichier dans chaque fichier qui utilise les constantes ou dans l'en-tête précompilé du projet.

Vous définissez ces constantes dans un fichier .m comme

// Constants.m
NSString *const MyFirstConstant = @"FirstConstant";
NSString *const MySecondConstant = @"SecondConstant";

Constants.m doit être ajouté à la cible de votre application / framework pour qu'il soit lié au produit final.

L'avantage d'utiliser des constantes de chaîne au lieu de #define'd constantes est que vous pouvez tester l'égalité en utilisant la comparaison de pointeurs (stringInstance == MyFirstConstant) qui est beaucoup plus rapide que la comparaison de chaînes ([stringInstance isEqualToString:MyFirstConstant]) (et plus facile à lire, IMO).


1236
2018-02-11 22:38



Moyen le plus simple:

// Prefs.h
#define PREFS_MY_CONSTANT @"prefs_my_constant"

Meilleure façon:

// Prefs.h
extern NSString * const PREFS_MY_CONSTANT;

// Prefs.m
NSString * const PREFS_MY_CONSTANT = @"prefs_my_constant";

Un avantage de la seconde est que la modification de la valeur d'une constante ne provoque pas une reconstruction de votre programme entier.


264
2018-02-11 22:02



Il y a aussi une chose à mentionner. Si vous avez besoin d'une constante non globale, vous devez utiliser static mot-clé.

Exemple

// In your *.m file
static NSString * const kNSStringConst = @"const value";

En raison de l static mot-clé, ce const n'est pas visible en dehors du fichier.


Correction mineure par @QuinnTaylor: les variables statiques sont visibles dans un unité de compilation. Habituellement, il s'agit d'un seul fichier .m (comme dans cet exemple), mais il peut vous mordre si vous le déclarez dans un en-tête qui est inclus ailleurs, car vous aurez des erreurs de liens après la compilation


182
2018-02-12 16:28



La réponse acceptée (et correcte) dit que "vous pouvez inclure ce fichier [Constants.h] ... dans l'en-tête pré-compilé pour le projet."

En tant que novice, j'ai eu du mal à le faire sans plus d'explications - voici comment: Dans votre fichier YourAppNameHere-Prefix.pch (c'est le nom par défaut pour l'en-tête précompilé dans Xcode), importez vos Constants.h à l'intérieur de #ifdef __OBJC__ bloc.

#ifdef __OBJC__
  #import <UIKit/UIKit.h>
  #import <Foundation/Foundation.h>
  #import "Constants.h"
#endif

Notez également que les fichiers Constants.h et Constants.m ne doivent contenir absolument rien d'autre sauf ce qui est décrit dans la réponse acceptée. (Pas d'interface ou de mise en œuvre).


117
2017-09-18 14:08



J'utilise généralement la manière affichée par Barry Wark et Rahul Gupta.

Bien que, je n'aime pas répéter les mêmes mots dans les fichiers .h et .m. Notez que dans l'exemple suivant, la ligne est presque identique dans les deux fichiers:

// file.h
extern NSString* const MyConst;

//file.m
NSString* const MyConst = @"Lorem ipsum";

Par conséquent, ce que j'aime faire est d'utiliser des machines de préprocesseur C. Laissez-moi expliquer à travers l'exemple.

J'ai un fichier d'en-tête qui définit la macro STR_CONST(name, value):

// StringConsts.h
#ifdef SYNTHESIZE_CONSTS
# define STR_CONST(name, value) NSString* const name = @ value
#else
# define STR_CONST(name, value) extern NSString* const name
#endif

Dans ma paire .h / .m où je veux définir la constante, je fais ce qui suit:

// myfile.h
#import <StringConsts.h>

STR_CONST(MyConst, "Lorem Ipsum");
STR_CONST(MyOtherConst, "Hello world");

// myfile.m
#define SYNTHESIZE_CONSTS
#import "myfile.h"

et voila, j'ai toutes les informations sur les constantes dans le fichier .h seulement.


50
2017-12-02 21:53



Une légère modification de la suggestion de @Krizz, afin que cela fonctionne correctement si le fichier d'en-tête de constantes doit être inclus dans le PCH, ce qui est plutôt normal. Puisque l'original est importé dans le PCH, il ne le rechargera pas dans le .m fichier et donc vous obtenez pas de symboles et l'éditeur de liens est mécontent.

Cependant, la modification suivante lui permet de fonctionner. C'est un peu compliqué, mais ça fonctionne.

Tu auras besoin 3 des dossiers, .h fichier qui a les définitions constantes, le .h fichier et le .m fichier, je vais utiliser ConstantList.h, Constants.h et Constants.m, respectivement. le contenu de Constants.h sont simplement:

// Constants.h
#define STR_CONST(name, value) extern NSString* const name
#include "ConstantList.h"

et le Constants.m le fichier ressemble à:

// Constants.m
#ifdef STR_CONST
    #undef STR_CONST
#endif
#define STR_CONST(name, value) NSString* const name = @ value
#include "ConstantList.h"

Finalement, le ConstantList.h fichier a les déclarations réelles en elle et c'est tout:

// ConstantList.h
STR_CONST(kMyConstant, "Value");
…

Un couple de choses à noter:

  1. J'ai dû redéfinir la macro dans le .m fichier après  #undefpour la macro à utiliser.

  2. Je devais aussi utiliser #include au lieu de #import pour que cela fonctionne correctement et évite au compilateur de voir les valeurs précédemment précompilées.

  3. Cela nécessitera une recompilation de votre PCH (et probablement du projet entier) chaque fois que des valeurs sont changées, ce qui n'est pas le cas si elles sont séparées (et dupliquées) comme d'habitude.

J'espère que c'est utile pour quelqu'un.


25
2017-12-03 00:03



J'ai moi-même un entête dédié à déclarer des NSStrings constants utilisés pour les préférences comme ceci:

extern NSString * const PPRememberMusicList;
extern NSString * const PPLoadMusicAtListLoad;
extern NSString * const PPAfterPlayingMusic;
extern NSString * const PPGotoStartupAfterPlaying;

Puis, en les déclarant dans le fichier .m d'accompagnement:

NSString * const PPRememberMusicList = @"Remember Music List";
NSString * const PPLoadMusicAtListLoad = @"Load music when loading list";
NSString * const PPAfterPlayingMusic = @"After playing music";
NSString * const PPGotoStartupAfterPlaying = @"Go to startup pos. after playing";

Cette approche m'a bien servi.

Edit: Notez que cela fonctionne mieux si les chaînes sont utilisées dans plusieurs fichiers. Si un seul fichier l'utilise, vous pouvez simplement le faire #define kNSStringConstant @"Constant NSString" dans le fichier .m qui utilise la chaîne.


24
2018-01-26 23:15



// Prefs.h
extern NSString * const RAHUL;

// Prefs.m
NSString * const RAHUL = @"rahul";

14
2017-09-28 04:37



Comme Abizer l'a dit, vous pouvez le mettre dans le fichier PCH. Un autre moyen qui n'est pas si sale est de créer un fichier d'inclusion pour toutes vos clés, puis de l'inclure dans le fichier dans lequel vous utilisez les clés ou de l'inclure dans PCH. Avec eux dans leur propre fichier d'inclusion, cela vous donne au moins un endroit pour rechercher et définir toutes ces constantes.


12
2018-02-11 22:05