web-dev-qa-db-fra.com

Où stocker les constantes globales dans une application iOS?

La plupart des modèles de mon application iOS interrogent un serveur Web. J'aimerais disposer d'un fichier de configuration contenant l'URL de base du serveur. Cela ressemblera à ceci:

// production
// static NSString* const baseUrl = "http://website.com/"

// testing
static NSString* const baseUrl = "http://192.168.0.123/"

En commentant l'une ou l'autre ligne, je peux changer instantanément le serveur vers lequel pointent les modèles. Ma question est la suivante: quelle est la meilleure pratique pour stocker des constantes globales dans iOS? Dans Android, nous avons intégré fichier de ressources de chaînes) . Dans any Activity (l’équivalent d’un IViewController ), 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?

109
JoJo

Vous pouvez aussi faire un

#define kBaseURL @"http://192.168.0.123/"

dans un fichier d'en-tête "constantes", dites constants.h. Alors fais

#include "constants.h"

en haut de chaque fichier où vous avez besoin de cette constante.

De cette façon, vous pouvez basculer entre les serveurs en fonction des drapeaux du compilateur, comme dans:

#ifdef DEBUG
    #define kBaseURL @"http://192.168.0.123/"
#else
    #define kBaseURL @"http://myproductionserver.com/"
#endif
145
Cyrille

Eh bien, vous voulez que la déclaration soit locale pour les interfaces auxquelles elle se rapporte - le fichier de constantes à l'échelle de l'application n'est pas une bonne chose.

De même, il est préférable de simplement déclarer un extern NSString* const symbole, plutôt que d'utiliser un #define:


SomeFile.h

extern NSString* const MONAppsBaseUrl;

Some.mile.m

#import "SomeFile.h"

#ifdef DEBUG
NSString* const MONAppsBaseUrl = @"http://192.168.0.123/";
#else
NSString* const MONAppsBaseUrl = @"http://website.com/";
#endif

Mis à part 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 votre *.m est bon.

167
justin

La façon dont je définis les constantes globales:


AppConstants.h

extern NSString* const kAppBaseURL;

AppConstants.m

#import "AppConstants.h"

#ifdef DEBUG
NSString* const kAppBaseURL = @"http://192.168.0.123/";
#else
NSString* const kAppBaseURL = @"http://website.com/";
#endif

Puis dans votre fichier {$ APP} -Prefix.pch:

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

Si vous rencontrez des problèmes, vérifiez d’abord que l’option En-tête de préfixe de précompilation est définie sur NO.

39
Piotr Tomasik

Vous pouvez également concaténer des constantes de chaîne comme ceci:

  #define kBaseURL @"http://myServer.com"
  #define kFullURL kBaseURL @"/api/request"
5
Martin Reichl

Je pense qu’une autre façon de faire est beaucoup plus simple et que vous allez simplement l’inclure dans les fichiers dont vous avez besoin d’être inclus, pas TOUS les fichiers, comme avec le fichier de préfixe .pch:

#ifndef Constants_h
#define Constants_h

//Some constants
static int const ZERO = 0;
static int const ONE = 1;
static int const TWO = 2;

#endif /* Constants_h */

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 l'inclure:

#include "Constants.h"
3
  1. Je définis une constante globale dans le fichier YOURPROJECT-Prefix.pch.
  2. #define BASEURl @"http://myWebService.appspot.com/xyz/xx"
  3. puis n'importe où dans le projet pour utiliser BASEURL:

    NSString *LOGIN_URL= [BASEURl stringByAppendingString:@"/users/login"];
    

Mise à jour: Dans Xcode 6, vous ne trouverez pas le fichier .pch par défaut créé dans votre projet. Veuillez donc utiliser fichier PCH dans Xcode 6 pour insérer le fichier .pch dans votre projet.

Mises à jour: Pour Swift

  1. Créer un nouveau fichier Swift [vide sans classe]), [AppGlobalMemebers]
  2. & Immédiatement déclarer/définir un membre

    Exemple:

    var STATUS_BAR_GREEN : UIColor  = UIColor(red: 106/255.0, green: 161/255.0, blue: 7/255.0, alpha: 1)  //
    
    1. Si vous souhaitez définir le membre global de l'application dans un fichier de classe, par exemple, classe Appdelegate ou Singleton ou tout autre, déclarez le membre spécifié ci-dessus à la définition de la classe.
3
Yogesh Lolusare

Les déclarations globales sont intéressantes mais, pour moi, ce qui a profondément changé ma façon de coder, c'est d'avoir des instances globales de classes. Il m'a fallu quelques jours pour vraiment comprendre comment travailler avec cela, 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 qu'un objet central gère toutes les tables de restaurant, vous créez l'objet au démarrage et c'est tout. Cet objet peut gérer les accès à la base de données OR le gérer en mémoire si vous n'avez pas besoin de le sauvegarder. Il est centralisé, vous affichez uniquement les interfaces utiles ...!

C'est une aide précieuse, orientée objet et un bon moyen de mettre toutes vos affaires au même endroit

Quelques lignes de code:

@interface RestaurantManager : NSObject
    +(id) sharedInstance;
    -(void)registerForTable:(NSNumber *)tableId;
@end 

et implémentation d'objet:

@implementation RestaurantManager

+ (id) sharedInstance {
    static dispatch_once_t onceQueue;

    dispatch_once(&onceQueue, ^{
        sharedInstance = [[self alloc] init];
        NSLog(@"*** Shared instance initialisation ***");
    });
    return sharedInstance;
}

-(void)registerForTable:(NSNumber *)tableId {
}
@end

pour l'utiliser c'est vraiment simple:

[[RestaurantManager sharedInstance] registerForTable: [NsNumero NumberWithInt: 10]]

2
Gregoire Mulliez

Une approche que j’ai utilisée auparavant consiste à créer un fichier Settings.plist et chargez-le dans NSUserDefaults au lancement à l'aide de registerDefaults:. Vous pouvez ensuite accéder à son contenu avec les éléments suivants:

// Assuming you've defined some constant kMySettingKey.
[[NSUserDefaults standardUserDefaults] objectForKey:kMySettingKey];

Bien que je n’aie effectué aucun développement Android), cela semble être 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 les paramètres. (par exemple en mode DEBUG.) Je suppose que vous pourriez charger dans un fichier différent, cependant.

NSUserDefaults documentation.

0
Chris Doble

Je voudrais utiliser un objet de configuration qui s'initialise à partir d'un plist. Pourquoi déranger les autres classes avec des éléments externes non pertinents?

J'ai crée eppz!settigns uniquement pour cette raison. Voir l'article moyen simple mais avancé pour sauvegarder dans NSUserDefaults pour incorporer les valeurs par défaut d'un plist.

enter image description here

0
Geri

La réponse acceptée a 2 faiblesses. Premièrement, comme d'autres l'ont souligné, l'utilisation de #define qui est plus difficile à déboguer, utilisez plutôt extern NSString* const kBaseUrl structure. Deuxièmement, il définit un fichier unique pour les constantes. IMO, cela est faux car la plupart des classes n'ont pas besoin d'accéder à ces constantes ou pour accéder à toutes les constantes, et le fichier peut devenir saturé si toutes les constantes y sont déclarées. Une meilleure solution serait de modulariser les constantes à 3 couches différentes:

  1. Couche système: SystemConstants.h ou AppConstants.h qui décrit les constantes au niveau global, accessible à n’importe quelle classe du système. Déclarez ici uniquement les constantes auxquelles il faut accéder à partir de classes différentes qui ne sont pas liées.

  2. Couche module/sous-système: ModuleNameConstants.h, décrit un ensemble de constantes typiques d'un ensemble de classes liées, à l'intérieur d'un module/sous-système.

  3. 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.

0
tesla

Pour un nombre, vous pouvez l'utiliser comme

#define MAX_HEIGHT 12.5
0
Gihan