La plupart des modèles de mon application iOS interrogent un serveur Web. Je souhaite avoir un fichier de configuration stockant l'URL de base du serveur. Cela ressemblera à quelque chose comme ceci:
// production
// static NSString* const baseUrl = "http://website.com/"
// testing
static NSString* const baseUrl = "http://192.168.0.123/"
En commentant une ligne ou une autre, je peux instantanément changer le serveur vers lequel mes modèles pointent. Ma question est la suivante: quelle est la meilleure pratique pour stocker des constantes globales dans iOS? Dans la programmation Android, nous avons ce fichier de ressources de chaînes intégré . Dans n'importe quelle activité (l'équivalent d'un UIViewController ), nous pouvons récupérer ces constantes de chaîne avec:
String string = this.getString(R.string.someConstant);
Je me demandais si le SDK iOS avait un emplacement analogue pour stocker les constantes. Si non, quelle est la meilleure pratique en Objective-C pour le faire?
"constants.h"
approche, déclarant desstatic
variables basées sur#ifdef VIEW_CONSTANTS ... #endif
. J'ai donc un fichier de constantes à l'échelle de l'application, mais chacun de mes autres fichiers de code a#define
différents ensembles de constantes à inclure avant#include
-ing le fichier de constantes (arrête tous les avertissements du compilateur "définis mais non utilisés").#decalare
, j'ai eu une erreur de compilation disant " directive de prétraitement invalide déclarer ". Alors je l'ai changé à la#define
place. L'autre problème est l'utilisation de la constante. Je voulais créer une autre constante avecstatic NSString* const fullUrl = [NSString stringWithFormat:@"%@%@", kbaseUrl, @"script.php"]
, mais apparemment, il est illégal de créer des consts avec une expression. J'obtiens l'erreur "l' élément d'initialisation n'est pas constant ".#define kBaseURL @"http://192.168.0.123/";
Eh bien, vous voulez que la déclaration soit locale aux interfaces auxquelles elle se rapporte - le fichier de constantes à l'échelle de l'application n'est pas une bonne chose.
De plus, il est préférable de simplement déclarer un
extern NSString* const
symbole, plutôt que d'utiliser un#define
:SomeFile.h
SomeFile.m
Outre l'omission de la déclaration Extern compatible C ++, c'est ce que vous verrez généralement utilisé dans les frameworks Obj-C d'Apple.
Si la constante doit être visible pour un seul fichier ou une seule fonction, alors
static NSString* const baseUrl
dans your*.m
is good.la source
@"foo"
n'est pas la même chose que[[NSString alloc] initWithCString:"foo"]
.#define
est utilisée (c'est-à-dire que l'égalité de pointeur peut échouer) - non pas qu'une expression littérale NSString produise un temporaire chaque fois qu'elle est exécutée.La façon dont je définis les constantes globales:
AppConstants.h
AppConstants.m
Puis dans votre fichier {$ APP} -Prefix.pch:
Si vous rencontrez des problèmes, assurez-vous d'abord que l'option En-tête de préfixe de précompilation est définie sur NON.
la source
Vous pouvez également concaténer des constantes de chaîne comme ceci:
la source
Je pense qu'une autre façon de faire est beaucoup plus simple et vous allez simplement l'inclure dans les fichiers dans lesquels vous en avez besoin, pas TOUS les fichiers, comme avec le fichier de préfixe .pch:
Après cela, vous incluez ce fichier d'en-tête dans le fichier d'en-tête souhaité. Vous l'incluez dans le fichier d'en-tête de la classe spécifique dans laquelle vous souhaitez qu'il soit inclus:
la source
"error: use of undeclared identifier .."
#define BASEURl @"http://myWebService.appspot.com/xyz/xx"
puis n'importe où dans le projet pour utiliser BASEURL:
Mise à jour: dans Xcode 6, vous ne trouverez pas de fichier .pch par défaut créé dans votre projet. Veuillez donc utiliser le fichier PCH dans Xcode 6 pour insérer un fichier .pch dans votre projet.
Mises à jour: pour SWIFT
& Déclarer / définir immédiatement un membre
Exemple:
la source
Les déclarations globales sont intéressantes mais, pour moi, ce qui a profondément changé ma façon de coder était d'avoir des instances globales de classes. Il m'a fallu quelques jours pour vraiment comprendre comment travailler avec, alors je l'ai rapidement résumé ici
J'utilise des instances globales de classes (1 ou 2 par projet, si nécessaire), pour regrouper l'accès aux données de base, ou certaines logiques de métiers.
Par exemple, si vous souhaitez avoir un objet central gérant toutes les tables de restaurant, vous créez votre objet au démarrage et c'est tout. Cet objet peut gérer les accès à la base de données OU le gérer en mémoire si vous n'avez pas besoin de l'enregistrer. C'est centralisé, vous ne montrez que les interfaces utiles ...!
C'est une aide précieuse, orientée objet et un bon moyen d'obtenir tout ce que vous avez au même endroit
Quelques lignes de code:
et implémentation d'objet:
pour l'utiliser c'est vraiment simple:
la source
La réponse acceptée a 2 faiblesses. Tout d'abord, comme d'autres l'ont souligné, son utilisation
#define
est plus difficile à déboguer, utilisez plutôt laextern NSString* const kBaseUrl
structure. Deuxièmement, il définit un fichier unique pour les constantes. OMI, c'est faux car la plupart des classes n'ont pas besoin d'accéder à ces constantes ou pour accéder à toutes et le fichier peut devenir gonflé si toutes les constantes y sont déclarées. Une meilleure solution serait de modulariser les constantes en 3 couches différentes:Couche système:
SystemConstants.h
ouAppConstants.h
qui décrit les constantes à portée globale, auxquelles toutes les classes du système peuvent accéder. Déclarez ici uniquement les constantes auxquelles il faut accéder à partir de différentes classes non liées.Couche module / sous-système:,
ModuleNameConstants.h
décrit un ensemble de constantes typiques d'un ensemble de classes associées, à l'intérieur d'un module / sous-système.Couche de classe: les constantes résident dans la classe et ne sont utilisées que par elle.
Seuls 1,2 sont liés à la question.
la source
Une approche que j'ai utilisée auparavant consiste à créer un fichier
Settings.plist
et à le chargerNSUserDefaults
au lancement en utilisantregisterDefaults:
. Vous pouvez ensuite accéder à son contenu avec les éléments suivants:Bien que je n'ai pas fait de développement Android, il semble que cela soit analogue au fichier de ressources de chaînes que vous avez décrit. Le seul inconvénient est que vous ne pouvez pas utiliser le préprocesseur pour permuter entre les paramètres (par exemple en
DEBUG
mode). Je suppose que vous pouvez cependant charger un fichier différent.NSUserDefaults
Documentation.la source
NSString
,NSNumber
, etc.). Bien sûr, vous pouvez envelopper vos#define
s pour faire la même chose, mais ils ne sont pas aussi faciles à modifier. L'plist
interface d'édition est également agréable. :) Bien que je convienne que vous ne devriez pas y mettre de trucs super secrets comme des clés de chiffrement, je ne suis pas trop préoccupé par les utilisateurs qui fouinent dans des endroits où ils ne devraient pas être - s'ils cassent l'application, c'est de leur propre faute .#define
s pour renvoyer le bon type, mais j'ai l'habitude d'éditer de tels fichiers de constantes, car j'ai toujours appris à mettre des constantes globales comme celle-ci dans un fichier de constantes séparé, à l'époque où j'ai appris Pascal sur un vieux 286 :) Et quant à l'utilisateur qui fouille partout, je suis d'accord aussi, c'est de sa faute. C'est juste une question de goût, vraiment.Pour un numéro, vous pouvez l'utiliser comme
la source
J'utiliserais un objet de configuration qui s'initialise à partir d'un fichier
plist
. Pourquoi déranger d'autres classes avec des éléments externes non pertinents?J'ai créé
eppz!settigns
uniquement pour cette raison. Voir l'article Moyen simple mais avancé d'enregistrer dans NSUserDefaults pour incorporer les valeurs par défaut d'un fichierplist
.la source