2010-07-22 9 views
11

Estoy usando un conjunto de Constant.m archivos, uno por objetivo, para definir cosas específicas para cada objetivo. Por ejemplo:¿Cómo puedo usar un NSArray como una constante global?

// Constants.h 
extern NSString * const kDatabaseFileName; 
//Constants.m 
NSString * const kDatabaseFileName = @"target_one.sqlite"; 

También me gustaría definir un NSArray para cada uno de mis objetivos:

NSArray * const kLabelNames = [[NSArray alloc] initWithObjects: 
    @"nameLabel", @"addressLabel", nil]; 

Pero esto da "error: elemento inicializador no es constante". El uso de 'arrayWithObjects` tampoco funciona. ¿Esto es porque las cadenas en mi matriz no son constantes?

¿Cómo puedo configurar una matriz como una constante global? Gracias.

+0

posible duplicado de [¿Cómo declaro una matriz como una constante en Objective-c?] (Http://stackoverflow.com/questions/2436463/how-do-i-declare-an-array- as-a-constant-in-objective-c) –

Respuesta

6

Si desea un conjunto de constantes que incluya tipos de NS, considere ubicarlos todos en un singleton.

Puede tener un único archivo de encabezado y varios archivos de implementación (uno por objetivo). Mientras todo eso implemente la clase declarada en el archivo de encabezado, debería estar bien.

2

Debe crear una clase que contenga las constantes en los métodos de clase. Luego puede agregar la clase a cualquier objetivo y llamar a los métodos para obtener constantes en objetos como matrices. Varíe la clase o la implementación de la clase para cambiar el retorno de las constantes.

Si lo usa mucho, puede crear un protocolo que defina los nombres de los métodos. A continuación, cambie la clase que implementa el protocolo en cada destino para que el mismo código devuelva diferentes valores según sea necesario.

28

En Objective-C, los objetos solo se pueden asignar en el montón, por lo que no hay forma de crear un NSArray en la memoria estática. Sin embargo, puede crear una matriz C de punteros a constantes NSString como así ...

NSString * const kLabelNames[] = { 
    @"Foo", @"Bar", @"Baz" 
}; 

... y entonces se puede escribir métodos de clase como ésta ...

+ (NSArray *)labelNames 
{ 
    static NSArray *names; 
    if (names == nil) { 
     names = [[NSArray alloc] initWithObjects:kLabelNames count:3]; 
    } 
    return names; 
} 

Editar

Tenga en cuenta que con la introducción de nuevas tecnologías como ARC, Grand Central Dispatch y la nueva sintaxis literal para matrices, ahora hay una forma más directa de lograr algo similar. Tenga en cuenta que el ejemplo a continuación también proporciona mayor seguridad de subprocesos, aunque el ejemplo original podría haber incorporado un bloque @synchronized, o uno de varios otros mecanismos, para lograr resultados similares.

+ (NSArray *)labelNames 
{ 
    static NSArray *names; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     names = @[@"Foo", @"Bar", @"Baz"]; 
    }); 

    return names; 
} 

Sin embargo, el ejemplo anterior no aborda por completo la pregunta original. Si realmente se necesita una matriz constante global, el ejemplo anterior se podría reescribir lo largo de líneas similares a la respuesta original, sin dejar de tomar ventaja de GCD:

NSString * const kLabelNames[] = { 
    @"Foo", @"Bar", @"Baz" 
}; 

+ (NSArray *)labelNames 
{ 
    static NSArray *names; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     names = [NSArray arrayWithObjects:kLabelNames count:3]; 
    }); 

    return names; 
} 
+0

En caso de que quiera reemplazar ese conteo: 3 por un valor dinámico, entonces puede usar la buena forma de C para obtener el tamaño de la matriz. '' 'count: sizeof (kLabelNames)/sizeof (kLabelNames [0])' '' –

1

Si se quiere evitar hacer una verificación de NULL en cada uso, puede crear una subclase del método NSObject + initialize. Se llamará una vez, la primera vez que se crea una instancia de su clase (y una vez más por subclase, si se crean instancias de alguna subclase), y es un muy buen lugar para realizar este tipo de inicialización.

http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html%23//apple_ref/occ/clm/NSObject/initialize

+1

Si lee el documento vinculado cuidadosamente, verá que 'initialize' se puede (y a menudo se llama) más de una vez:" El tiempo de ejecución envía 'initialize' a cada clase en un programa exactamente una vez justo antes de que la clase, * o cualquier clase que herede de ella *, se envíe su primer mensaje desde el programa." [énfasis agregado] – jlehr

+0

Acabo de ver su comentario y actualicé mi respuesta. – StilesCrisis

5

Aquí es un enfoque mucho más simple:

Declarar NSString con elementos separados por comas (o cualquier delimitador desea)

NSString *const kLabelNames = @"Foo,Bar,Baz"; 

A continuación, convertir a NSArray siempre que lo necesite:

NSArray *namesArray = [kLabelNames componentsSeparatedByString:@","]; 
4

Usa una macro:

#define SOME_ARRAY (@[@"blah", @"asdf", @"qwerty"]) 
Cuestiones relacionadas