2010-03-12 19 views
57

El siguiente código es que me da errores:¿Cómo declaro una matriz como una constante en Objective-c?

// constants.h 
extern NSArray const *testArray;
// constants.m 
NSArray const *testArray = [NSArray arrayWithObjects: @"foo", @"bar", nil];

El error que consigo es
initializer element is not constant

O si yo quite el indicador de puntero (*) me sale:
statically allocated instance of Objective-C class 'NSArray'

+1

Por 'constante' ¿qué quieres decir? Contenido inmutable del objeto, o puntero inmutable? – zneak

+0

Bueno, mis criterios son: 1) Los valores no se pueden cambiar accidentalmente (entonces supongo que NSArray es bueno), 2) disponibles en cualquier parte del programa (estoy incluyendo 'constants.h' en mi archivo .pch), 3) Solo se ha declarado una vez – Andrew

+1

[Ver esta pregunta TAN] (http://stackoverflow.com/questions/1059708/defining-a-constant-in-objective-c) – conorgriffin

Respuesta

65

En resumen, no se puede. Los objetos Objective-C, con la excepción de las constantes NSString, solo se crean en el tiempo de ejecución y, por lo tanto, no se puede usar una expresión para inicializarlos.

Hay varios enfoques.

(1) Declare NSArray *testArray sin la palabra clave const y luego tenga un poco de código que configura el valor que se invoca muy temprano durante el ciclo de vida de la aplicación.

(2) Declare un método de clase conveniente que devuelve el conjunto, luego use un static NSArray *myArray dentro de ese método y trátelo como un singleton (busque SO en "objetivo-c singleton" para un millón de respuestas sobre cómo crear instancias) .

+5

Si solo se trata de una matriz de 'NSStrings 'como en la pregunta, podría crear una matriz de estilo' C' en su archivo de constantes y luego usar algunos métodos 'C' para acceder a los valores. Ver [mi respuesta a continuación] (http://stackoverflow.com/a/11485727/630996) – AngeloS

+2

@bbum - esto sigue siendo cierto incluso con el azúcar '@ [...]', ¿sí? –

+0

@BenMosher Correcto; el azúcar simplemente se traduce a llamadas en tiempo de ejecución ... – bbum

6

Es bastante fácil:

#define arrayTitle [NSArray arrayWithObjects: @"hi",@"foo",nil]

puesto antes de la implementación y sin punto y coma.

Espero que ayude.

+55

Eso realmente no le da una matriz constante, solo genera una nueva cada vez que usa 'arrayTitle', – Abizern

+3

Eso no es una matriz constante en absoluto ... – DZenBot

+8

Sin embargo, ayuda a otras personas que visitan el hilo más tarde, que solo quiere declarar en el archivo de encabezado, pero no le importa hacer una constante. –

31

Un poco tarde para la fiesta, pero como no está cambiando los valores a lo largo del programa, si solo estaba tratando con cadenas, puede hacer lo siguiente declarando su matriz usando una matriz C:

extern NSString * const MY_CONSTANT_STRING_ARRAY[]; 

en su archivo constants.h, y luego en su constants.m se podría añadir objetos a la misma, así:

NSString * const MY_CONSTANT_STRING_ARRAY[] = { @"foo", @"bar" }; 

a continuación, para acceder a un miembro, usted podría hacer un bucle al igual que el ingenio ja Csizeof() operador:

Esto, obviamente, es una matriz C y no un NSArray para que no se consigue todos los métodos de diversión que se le atribuye como objectAtIndex:, por lo que podría crear una función de ayuda en alguna parte de su programa que se repite a través de todas las cadenas usando el método que describí anteriormente y devuelve un NSArray (o NSMutableArray par). Pero, si estaba haciendo lo que hago y solo necesita una matriz constante de valores NSString para utilizar en su programa, este método funciona mejor.

Hacerlo de esta manera encapsula todas sus contants matriz de cadenas en constants.h, y que está disponible a través de su programa agregando constants.h en su archivo .pch en lugar de crear un producto único sólo para este conjunto de valores o la creación de la matriz con un poco código, que sorta derrota el propósito de un archivo constants porque elimina las constantes reales del archivo constants ..

EDITAR por @ Comentario de JesseGumpo:

Dado que puede haber problemas con el uso sizeof() para determinar el tamaño de la matriz, una solución sencilla consiste en declarar el tamaño de la matriz en sus constantes presentar de este modo:

//.h 
extern int SIZE_OF_MY_CONSTANTS_ARRAY; 

///.m 
int SIZE_OF_MY_CONSTANTS_ARRAY = 2; 

Y a continuación, para acceder a los miembros en un bucle for puede hacerlo de esta manera:

for (int i=0; i < SIZE_OF_MY_CONSTANTS_ARRAY; i++) 
     NSLog(@"my constant string is: %@", MY_CONSTANT_STRING_ARRAY[i]); 

Sí, esto no captura dinámicamente el tamaño de la matriz, pero si declara una matriz en un archivo de constantes, ya conoce el tamaño de esa matriz desde el principio, por lo que a pesar de que agrega dos líneas más de código, todavía logra la tarea de tener una matriz en un archivo de constantes.

Si alguien tiene más sugerencias o puede conocer algunos otros trucos de C por favor deje un comentario abajo!

+0

Esto es incorrecto. sizeof() devuelve el tamaño de la memoria. Es probable que esto pase por 8 iteraciones, pero falla en el tercer –

+0

@JesseGumpo, gracias por ese comentario. En mi implementación real, creé una constante int para el tamaño de la matriz en lugar de usar 'sizeof()'. Editaré mi respuesta para reflejar mi enfoque final, que como usa tipos de datos simples, todavía funciona y cumple la tarea de tener una matriz en un archivo de constantes. – AngeloS

+7

"sizeof (MY_CONSTANT_STRING_ARRAY)/sizeof (MY_CONSTANT_STRING_ARRAY [0])" lo haría – boecko

9

Aquí hay una macro para hacerlo en una línea para una instancia estática en un ámbito de método.

#define STATIC_ARRAY(x, ...) \ 
     static NSArray* x=nil; \ 
     static dispatch_once_t x##onceToken; \ 
     dispatch_once(&x##onceToken, ^{ x = @[ __VA_ARGS__ ]; }); 

Uso ejemplo

STATIC_ARRAY(foo, @"thing1", @"thing2", [NSObject new]); 
+0

¡Este es un buen fragmento! ¡Me gusta mucho! – Septronic

3

En cuanto a mí, es más conveniente utilizar la siguiente implementación de una serie de constantes

static NSString * kHeaderTitles [3] = {@ "ACCOUNT DETAILS", @ "SOCIAL NETWORK", @ "SETTINGS"}; 
static int kNumbers[3] = {1, 2, 3}; 
3

Tengo un archivo de cabecera llamada "Constantes. h "y dentro de las siguientes matrices constantes:

#define arrayOfStrings @[@"1", @"2", @"3", @"4"] 
#define arraysOfIds @[@(1), @(2), @(3), @(4)] 

Básicamente, cuando llama a arrayOfStrings en su código, se reemplaza con @ [@ "1", @ "2", @ "3", @ "4"] y lo mismo con arraysOfIds.

+1

Esto también causará que * se cree una * nueva instancia de la matriz * cada vez que se mencione 'arrayOfStrings' o' arraysOfIds'. – bbum

Cuestiones relacionadas