Dónde almacenar constantes globales en una aplicación de iOS?

La mayoría de los modelos en mi aplicación iOS consultan un servidor web. Me gustaría tener un archivo de configuración que almacene la URL base del servidor. Se verá algo como esto:

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

Al comentar una línea o la otra, puedo cambiar instantáneamente a qué servidor apuntan mis modelos. Mi pregunta es, ¿cuál es la mejor práctica para almacenar constantes globales en iOS? En la progtwigción de Android, tenemos este archivo de recursos de cadenas integrado. En cualquier actividad (el equivalente de un UIViewController ), podemos recuperar esas constantes de cadena con:

 String string = this.getString(R.string.someConstant); 

Me preguntaba si el iOS SDK tiene un lugar análogo para almacenar constantes. Si no, ¿cuál es la mejor práctica en Objective-C para hacerlo?

También podrías hacer un

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

en un archivo de encabezado “constantes”, diga constants.h . Entonces hazlo

 #include "constants.h" 

en la parte superior de cada archivo donde necesitas esta constante.

De esta forma, puede cambiar entre servidores dependiendo de los indicadores del comstackdor, como en:

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

Bueno, desea la statement local para las interfaces a las que se refiere: el archivo de constantes para toda la aplicación no es bueno.

Además, es preferible simplemente declarar un símbolo extern NSString* const , en lugar de usar un #define :


SomeFile.h

 extern NSString* const MONAppsBaseUrl; 

SomeFile.m

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

Además de la omisión de la statement externa compatible con C ++, esto es lo que generalmente verá utilizado en los marcos Obj-C de Apple.

Si la constante necesita ser visible para un solo archivo o función, entonces static NSString* const baseUrl en su *.m es buena.

La forma en que defino las 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 

Luego, en su archivo {$ APP} -Prefix.pch:

 #ifdef __OBJC__ #import  #import  #import "AppConstants.h" #endif 

Si tiene algún problema, primero asegúrese de tener la opción de encabezado del prefijo Precomstackr en NO.

También puede concatenar constantes de cadena como esta:

  #define kBaseURL @"http://myServer.com" #define kFullURL kBaseURL @"/api/request" 
  1. Defino la constante global en el archivo YOURPROJECT-Prefix.pch.
  2. #define BASEURl @"http://myWebService.appspot.com/xyz/xx"
  3. entonces en cualquier lugar del proyecto para usar BASEURL:

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

Actualizado: En Xcode 6 no encontrará el archivo .pch predeterminado creado en su proyecto. Por lo tanto, utilice PCH File en Xcode 6 para insertar el archivo .pch en su proyecto.

Actualizaciones: para SWIFT

  1. Crear nuevo archivo Swift [vacío sin clase] decir [AppGlobalMemebers]
  2. & Inmediatamente declarar / definir miembro

    Ejemplo:

     var STATUS_BAR_GREEN : UIColor = UIColor(red: 106/255.0, green: 161/255.0, blue: 7/255.0, alpha: 1) // 
    1. Si desea definir el miembro global de la aplicación en cualquier archivo de clase, digamos Appdelegate o Singleton class o any, declare el miembro dado por encima de la definición de la clase

Creo que otra forma de hacerlo es mucho más simple y solo la incluirá en los archivos en los que los necesita, no en TODOS los archivos, como con el archivo de prefijo .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 */ 

Después de eso, incluye este archivo de encabezado en el archivo de encabezado que desea. Lo incluye en el archivo de encabezado para la clase específica en la que desea que esté incluido:

 #include "Constants.h" 

Las declaraciones globales son interesantes pero, para mí, lo que cambió profundamente mi camino al código fue tener instancias globales de clases. Me tomó un par de días entender realmente cómo trabajar con él, así que lo resumí rápidamente aquí

Utilizo instancias globales de clases (1 o 2 por proyecto, si es necesario) para reagrupar el acceso a los datos centrales, o algunas lógicas comerciales.

Por ejemplo, si desea tener un objeto central manejando todas las tablas de restaurante que crea, objeta al inicio y eso es todo. Este objeto puede manejar accesos a la base de datos O manejarlo en la memoria si no necesita guardarlo. ¡Está centralizado, muestra solo interfaces útiles …!

Es una gran ayuda, orientada a objetos y una buena forma de obtener todo lo que tienes en el mismo lugar

Algunas líneas de código:

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

y la implementación de objetos:

 @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 

para usarlo es realmente simple:

[[RestaurantManager sharedInstance] registerForTable: [NsNumber numberWithInt: 10]]

Un enfoque que he usado anteriormente es crear un archivo Settings.plist y cargarlo en NSUserDefaults al iniciar usando registerDefaults: A continuación, puede acceder a su contenido con lo siguiente:

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

Si bien no he hecho ningún desarrollo de Android, parece que es análogo al archivo de recursos de cadenas que describió. El único inconveniente es que no puede usar el preprocesador para intercambiar configuraciones (por ejemplo, en el modo DEBUG ). Sin embargo, supongo que podrías cargar un archivo diferente.

Documentación NSUserDefaults .

Para un número puedes usarlo como

 #define MAX_HEIGHT 12.5 

La respuesta aceptada tiene 2 debilidades. En primer lugar, como otros señalaron el uso de #define que es más difícil de depurar, use en su lugar extern NSString* const kBaseUrl estructura extern NSString* const kBaseUrl . Segundo, define un solo archivo para constantes. OMI, esto es incorrecto porque la mayoría de las clases no necesitan acceso a esas constantes o para acceder a todas ellas más el archivo puede hincharse si todas las constantes se declaran allí. Una mejor solución sería modular constantes en 3 capas diferentes:

  1. Capa del sistema: SystemConstants.h o AppConstants.h que describe las constantes en el scope global, a las que se puede acceder desde cualquier clase del sistema. Declare aquí solo las constantes a las que se debe acceder desde diferentes clases que no están relacionadas.

  2. Capa de módulo / ModuleNameConstants.h : ModuleNameConstants.h , describe un conjunto de constantes que son típicas para un conjunto de clases relacionadas, dentro de un módulo / subsistema.

  3. Capa de clase: Constantes reside en la clase y solo la usa.

Solo 1,2 están relacionados con la pregunta.

plist un objeto de configuración que se inicializa desde un plist . ¿Por qué molestar a otras clases con cosas externas irrelevantes?

eppz!settigns por este motivo. Vea el artículo Una forma simple y avanzada de guardar en NSUserDefaults para incorporar valores predeterminados de un plist .

enter image description here