2012-02-12 17 views
36

Estoy desarrollando una aplicación en este momento que obtiene recursos de una API JSON.¿Cuál es el mejor lugar para almacenar constantes en una aplicación de iOS?

todos los recursos tienen el mismo URL base:

http://api.mysite.com/resources.json 
http://api.mysite.com/other_resources.json 

quiero almacenar la cadena http://api.mysite.com/ para que esté disponible a todos mis controladores y modelos, la eliminación de algunas duplicaciones al escribir las direcciones URL de recursos.

¿Cuál es el mejor lugar para hacer esto? El archivo -prefix.pch?

Algún consejo apreciado

Respuesta

64

estoy de acuerdo con la respuesta de Alex Coplan con una adición importante.

poner todas sus constantes en un archivo llamado "constants.h" (o w/e desea)

EDIT:

  • Cuando respondí esta pregunta hace tres años, yo estaba en el #define vagón, verifique a continuación para una revisión.

constants.h

#define kFilterDate @"date" 
#define kFilterRadius @"radius" 
#define kFilterSort @"sort" 

//Global Strings 
#define kDividingString @"/" 

//Strings 
#define kTour @"Tour" 
#define kToursKey @"tours" 

Pero en lugar de importarlo en cualquier archivo que lo necesite, importarlo en su archivo de prefijo de modo que todas sus cabeceras importar de forma automática a través de su proyecto.

Project_Prefix.pch

// 
// Prefix header for all source files of the project 
// 

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

REVISIÓN

Todos sin embargo toda la información anterior seguirá funcionando, hay algunas cosas que podemos hacer para ser un poco más segura acerca de nuestros constantes.

Cree sus constantes en su archivo Constants.h utilizando variables const

//Filters 
FOUNDATION_EXPORT NSString *const kFilterDate; 
FOUNDATION_EXPORT NSString *const kFilterRadius; 
FOUNDATION_EXPORT NSString *const kFilterSort; 

//Global Strings 
FOUNDATION_EXPORT NSString *const kDividingString; 

//Strings 
FOUNDATION_EXPORT NSString *const kTour; 
FOUNDATION_EXPORT NSString *const kToursKey; 

Y en Constants.m

//Filters 
NSString *const kFilterDate = @"date"; 
NSString *const kFilterRadius = @"radius"; 
NSString *const kFilterSort = @"sort"; 

//Global Strings 
NSString *const kDividingString = @"/"; 

//Strings 
NSString *const kTour = @"Tour"; 
NSString *const kToursKey = @"tours"; 

Esto todavía puede ser importado a su archivo de prefijo como el anterior, pero sólo usar constantes que son verdaderamente global en el archivo para hacer eso. Los que se utilizan con frecuencia en muchos lugares. Volcar todas sus constantes en este archivo hará que su código que usa cualquier constante se acople al archivo de constantes. Por lo tanto, si intenta volver a utilizar el código, el archivo de constantes debe venir con él.Esto no siempre es necesariamente malo, y muchas veces está destinado (lo cual está bien), pero limitar las dependencias siempre es una buena idea.

algunas cosas acerca de la revisión:

  • FOUNDATION_EXPORT vs extern. El primero compila diferentes para C y C++. Básicamente significa extern, pero en C++ agregará la bandera "C".
  • consts vs defines. consts son seguros y respetan el alcance. defines son exactamente lo contrario.
+0

Odio usar '.h .m' para las constantes globales. ¡Tener que escribir cada nombre de variable DOS VECES es un DOLOR! – Hlung

+3

Tener un código limpio, consistente y legible vale 10 veces más que el doble de su dolor. – ColdLogic

+0

Para el caso siguiente, ¿qué debo hacer? soy un error "elemento de inicialización no es constante de tiempo de compilación para USER_LIST_URL" NSString *const SERVER_URL = @"http://www.google.com"; NSString *const USER_LIST_URL = [NSString stringWithFormat:@"%@/xml/index.cfm",SERVER_URL];

4

me gustaría crear un producto único o utilizar el AppDelegate y poner las constantes allí.

+0

Pensaré muy cuidadosamente antes de crear un singleton: hacen las pruebas unitarias muy difíciles y normalmente es posible lograr lo mismo sin una. Usar el delegado de la aplicación es una mejor solución, pero aún no es ideal. Muchos considerarían que es un mal diseño colocar demasiada responsabilidad en el delegado de la aplicación. Optaría personalmente por crear un archivo de encabezado global que solo contenga constantes según la respuesta de Alex Coplan. –

+0

@WillPragnell ¿De qué manera el archivo de encabezado hace que las pruebas unitarias sean más sencillas que un Singleton? En general, Singleton dificulta las pruebas unitarias, pero parece ser exactamente el lugar donde brilla Singleton. – Jackson

11

acabo de crear un archivo llamado Globals.h con algo como lo siguiente:

#define kBaseURL @"http://api.mysite.com/" 

Luego de usar:

#import "Globals.h" // at the top 

NSString *url = [NSString stringWithFormat:@"%@resources.json",kBaseURL]; 
+0

Creo que esta es la mejor manera de hacerlo. –

4

Sí, un encabezado global sería una solución ideal. No llegaría tan lejos como un patrón único, a menos que planee usarlo para otras cosas como administrar su almacén de datos. Un singleton para globales es algo exagerado.

48

Personalmente, prefiero usar variables de const reales en lugar de definirlas.

En un archivo MyConstants.m que tengo:

NSString *const kXYMySiteBaseURL = @"http://api.mysite.com/"; 
NSString *const kXYSomeOtherURL = @"http://www.google.com/"; 

donde XY es mis iniciales o algún otro prefijo "única" para evitar colisiones con otras constantes.

entonces tengo un archivo MyConstants.h así:

extern NSString *const kXYMySitBaseURL; 
extern NSString *const kXYSomeOtherURL; 

Dependiendo de la cantidad de archivos que tenga que acceder a estas constantes, podría incluirlo en el encabezado precompilado como ColdFusion sugiere en su respuesta.

Así es como Apple define sus constantes en la mayoría de los frameworks Core.

+2

Sé que es probablemente una diferencia insignificante, pero ¿cuáles son las implicaciones en la memoria de definir una constante una vez (que vive para la duración de su aplicación) VS que define instancia/variable local usando macros que se usan y luego se someten a GC sobre la marcha? – bodacious

+0

como puede leer aquí https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingIvarsAndTypes.html, Apple le recomienda no utilizar las macros #define. Es por eso que prefiero esta respuesta que la anterior – voghDev

+0

Es un poco de ahorro de memoria. También existe la ventaja de que cosas como isEqual: o isEqualToString ni siquiera se molestará en comparar las cadenas porque son el mismo puntero. – gnasher729

Cuestiones relacionadas