Как объявить массив как константу в Objective-c?

Следующий код дает мне ошибки:

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

Ошибка, которую я получаю, - это initializer element is not constant

Или, если я заберу указатель указателя (*), я получу:
 statically allocated instance of Objective-C class 'NSArray'

Ответ 1

Короче говоря, вы не можете. Objective-C объекты, за исключением констант NSString, создаются только во время выполнения и, следовательно, вы не можете использовать выражение для их инициализации.

Существует несколько подходов.

(1) Объявите NSArray *testArray без ключевого слова const, а затем немного кода, который устанавливает значение, которое вызывается очень рано в течение жизненного цикла приложения.

(2) Объявите удобный метод класса, который возвращает массив, затем используйте static NSArray *myArray внутри этого метода и рассмотрите его как одноэлементный (поиск SO для "objective-c singleton" примерно за два миллиона ответов о том, как создать экземпляр).

Ответ 2

Немного поздно для вечеринки, но поскольку вы не меняете значения по ходу программы, если вы имеете дело со строками, вы можете сделать следующее, объявив свой массив с помощью массива C:

extern NSString * const MY_CONSTANT_STRING_ARRAY[];

в вашем файле constants.h, а затем в constants.m вы можете добавлять к нему объекты следующим образом:

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

Затем, чтобы получить доступ к члену, вы можете сделать цикл for так же, как с оператором C sizeof():

Это, очевидно, массив C, а не NSArray, поэтому вы не получите все приложенные к нему методы удовольствия, например objectAtIndex:, поэтому вы можете создать вспомогательную функцию где-нибудь в вашей программе, которая проходит через все строки, используя описанный выше метод, и возвращает NSArray (или NSMutableArray четный). Но если вы делаете то, что мне нужно, и вам нужен постоянный массив значений NSString для использования во всей вашей программе, этот метод работает наилучшим образом.

Выполнение этого способа инкапсулирует все ваши строковые массивы в constants.h и по-прежнему доступно во всей вашей программе, добавив constants.h в ваш файл .pch вместо создания синглета только для этого массива значений или настройки массив с небольшим кодом, который sorta поражает цель файла constants, поскольку он удаляет фактические константы из файла constants..

РЕДАКТИРОВАТЬ за комментарий @JesseGumpo:

Так как могут возникнуть проблемы с использованием sizeof() для определения размера массива, простым обходным путем является объявление размера массива в файле констант следующим образом:

//.h
extern int SIZE_OF_MY_CONSTANTS_ARRAY;  

///.m
int SIZE_OF_MY_CONSTANTS_ARRAY = 2;

И затем для доступа к членам в цикле for вы можете сделать это следующим образом:

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

Да, это не динамически захватывает размер массива, но если вы объявляете массив в файле констант, вы уже знаете размер этого массива с самого начала, поэтому, хотя он добавляет еще две строки кода, он все еще выполняет задачу наличия массива в файле констант.

Если у кого-то есть дополнительные предложения или могут быть известны другие трюки C, пожалуйста, оставьте комментарий ниже!

Ответ 3

Здесь макрос, чтобы сделать это в одной строке для статического экземпляра в области метода.

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

Пример использования

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

Ответ 4

Это довольно легко:

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

поставить перед реализацией и без точки с запятой.

надеюсь, что это поможет.

Ответ 5

Для меня удобнее использовать следующую реализацию для массива констант

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

Ответ 6

У меня есть заголовочный файл под названием "Constants.h" и в следующих постоянных массивах:

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

В основном, когда вы вызываете arrayOfStrings в вашем коде, его заменяют на @[@ "1", @ "2", @ "3", @ "4" ] и то же самое на arraysOfIds.