web-dev-qa-db-fra.com

Comment déclarer un tableau comme constante dans Objective-c?

Le code suivant me donne des erreurs:

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

L'erreur que j'obtiens est
initializer element is not constant

Ou si je retire l'indicateur de pointeur (*) j'obtiens:
statically allocated instance of Objective-C class 'NSArray'

63
Andrew

Bref, vous ne pouvez pas. Les objets Objective-C sont, à l'exception des constantes NSString, uniquement créés au moment de l'exécution et, par conséquent, vous ne pouvez pas utiliser une expression pour les initialiser.

Il existe une poignée d'approches.

(1) Déclarer NSArray *testArray sans le mot clé const, puis disposez d'un peu de code qui définit la valeur qui est appelée très tôt pendant le cycle de vie de l'application.

(2) Déclarez une méthode de classe pratique qui renvoie le tableau, puis utilisez un static NSArray *myArray dans cette méthode et la traiter comme un singleton (recherchez SO pour "objective-c singleton" pour environ un million de réponses sur la façon d'instancier).

69
bbum

Un peu tard pour la fête, mais comme vous ne modifiez pas les valeurs au cours du programme, si vous ne traitez qu'avec des chaînes, vous pouvez effectuer les opérations suivantes en déclarant votre tableau à l'aide d'un tableau C:

extern NSString * const MY_CONSTANT_STRING_ARRAY[];

dans votre fichier constants.h, puis dans votre constants.m vous pouvez y ajouter des objets comme ceci:

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

Ensuite, pour accéder à un membre, vous pouvez faire une boucle for comme celle-ci avec un opérateur Csizeof():

Il s'agit évidemment d'un tableau C et non d'un NSArray donc vous n'avez pas toutes les méthodes amusantes qui y sont attachées comme objectAtIndex:, Vous pouvez donc créer une fonction d'aide quelque part dans votre programme qui parcourt toutes les chaînes en utilisant la méthode décrite ci-dessus et renvoie un NSArray (ou NSMutableArray pair). Mais, si vous faisiez ce que je suis et que vous avez juste besoin d'un tableau constant de valeurs NSString à utiliser dans votre programme, cette méthode fonctionne le mieux.

En procédant de cette façon, vous encapsulez tous vos contenus de tableau de chaînes dans constants.h, Et vous êtes toujours disponible dans votre programme en ajoutant constants.h Dans votre fichier .pch Au lieu de créer un singleton juste pour ce tableau de valeurs ou la définition du tableau avec un peu de code, ce qui va à l'encontre de l'objectif d'un fichier constants car il supprime les constantes réelles du fichier constants ..

EDIT selon le commentaire de @ JesseGumpo:

Puisqu'il peut y avoir des problèmes avec l'utilisation de sizeof() pour déterminer la taille du tableau, une solution simple consiste à déclarer la taille du tableau dans votre fichier de constantes comme suit:

//.h
extern int SIZE_OF_MY_CONSTANTS_ARRAY;  

///.m
int SIZE_OF_MY_CONSTANTS_ARRAY = 2;

Et puis pour accéder aux membres dans une boucle for, vous pouvez le faire comme ceci:

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

Oui, cela ne capture pas dynamiquement la taille du tableau, mais si vous déclarez un tableau dans un fichier de constantes, vous connaissez déjà la taille de ce tableau depuis le début, donc même s'il ajoute deux lignes de code supplémentaires, il accomplit toujours la tâche d'avoir un tableau dans un fichier de constantes.

Si quelqu'un a d'autres suggestions ou peut connaître d'autres astuces C, veuillez laisser un commentaire ci-dessous!

33
AngeloS

Voici une macro pour le faire en une seule ligne pour une instance statique dans une portée de méthode.

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

Utiliser l'exemple

    STATIC_ARRAY(foo, @"thing1", @"thing2", [NSObject new]);
9
JoeM

Quant à moi, il est plus pratique d'utiliser l'implémentation suivante pour un tableau de constantes

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

C'est assez simple:

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

mettre avant la mise en œuvre et sans point-virgule.

j'espère que ça aide.

6
HelmiB

J'ai un fichier d'en-tête appelé "Constants.h" et dans les prochains tableaux constants:

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

Fondamentalement, lorsque vous appelez arrayOfStrings dans votre code, il est remplacé par @ [@ "1", @ "2", @ "3", @ "4"] et la même chose avec arraysOfIds.

3