Как я могу использовать NSArray в качестве глобальной константы? - PullRequest
11 голосов
/ 22 июля 2010

Я использую набор Constant.m файлов, по одному на цель, чтобы определить конкретные вещи для каждой цели. Например:

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

Я также хотел бы определить NSArray для каждой из моих целей:

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

Но это дает "ошибку: элемент инициализатора не является константой". Использование 'arrayWithObjects` также не работает. Это потому, что строки в моем массиве не являются константами?

Как я могу установить массив как глобальную константу? Благодаря.

Ответы [ 6 ]

28 голосов
/ 23 июля 2010

В Objective-C объекты могут размещаться только в куче, поэтому нет способа создать NSArray в статической памяти. Тем не менее, вы можете создать массив C указателей на константы NSString, например так ...

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

... и тогда вы можете написать методы класса, подобные этому ...

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

Редактировать

Обратите внимание, что с появлением новых технологий, таких как ARC, Grand Central Dispatch и нового буквального синтаксиса для массивов, теперь есть более простой способ сделать что-то подобное. Обратите внимание, что приведенный ниже пример также обеспечивает большую безопасность потоков, хотя исходный пример мог включать в себя блок @synchronized или один из нескольких других механизмов для достижения аналогичных результатов.

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

    return names;
}

Однако приведенный выше пример не полностью отвечает первоначальному вопросу. Если глобальный константный массив действительно необходим, предыдущий пример может быть переписан в том же ключе, что и исходный ответ, при этом все еще используя 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;
}
6 голосов
/ 12 мая 2014

Вот гораздо более простой подход:

Объявление NSString с разделенными запятыми элементами (или любым другим разделителем, который вы хотите)

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

Затем конвертируйте в NSArray, когда вам это нужно:

NSArray *namesArray = [kLabelNames componentsSeparatedByString:@","];
6 голосов
/ 23 июля 2010

Если вам нужен набор констант, который включает в себя типы NS, рассмотрите возможность размещения их всех в одиночном.

Вы можете иметь один заголовочный файл и несколько файлов реализации (по одному на цель). До тех пор, пока все они реализуют класс, объявленный в заголовочном файле, все будет в порядке.

5 голосов
/ 25 марта 2015

Использовать макрос:

#define SOME_ARRAY (@[@"blah", @"asdf", @"qwerty"])
2 голосов
/ 23 июля 2010

Вы должны создать класс, который содержит константы в методах класса.Затем вы можете добавить класс к любой цели и вызвать методы для получения констант в таких объектах, как массивы.Изменяйте класс или реализацию класса, чтобы изменить возвращаемую константу.

Если вы часто его используете, вы можете создать протокол, который определяет имена методов.Затем поменяйте класс, который реализует протокол в каждой цели, чтобы тот же код возвращал разные значения по мере необходимости.

1 голос
/ 18 мая 2011

Если вы хотите избежать проверки NULL при каждом использовании, вы можете создать подкласс метода инициализации NSObject +.Это будет вызвано один раз, в первый раз, когда создается экземпляр вашего класса (и еще раз для каждого подкласса, если создаются экземпляры каких-либо подклассов), и это очень хорошее место для такой инициализации.

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

...