Константы NSNumber в Obj-C
Я хочу сделать некоторые константы NSNumber с помощью того же стиля, который использовался для NSStrings в в этом разделе. То есть я создаю отдельные файлы констант .h/.m и импортирую их в классы, которым необходимо получить к ним доступ.
Ответы
Ответ 1
Проблема с этим заключается в том, что нет такой вещи, как константа NSNumber времени компиляции. Только NSString получает это различие. NSNumbers всегда создаются динамически. Вы можете подделать его, используя функцию, запускаемую при запуске вашей программы, для инициализации переменных. Ваши варианты:
-
Создайте класс с помощью метода +load
, который выполняет инициализацию.
-
В файле с константами включите функцию с __attribute__((constructor))
. Итак, например:
// Constants.m
NSNumber *someGlobalNumber;
__attribute__((constructor))
static void InitGlobalNumber() {
someGlobalNumber = [[NSNumber numberWithInteger:1] retain];
}
Но, конечно, вы не можете надежно использовать эти числа в любых других функциях, которые запускаются в начале процесса запуска. Это обычно не проблема, но стоит иметь в виду.
Другой вариант, который я видел несколько раз, заключается в том, чтобы иметь класс с аксессуарами для чисел вместо того, чтобы давать необработанный доступ к переменным. Это немного более тяжелый дизайн, но он также чувствует себя менее вудуидным, у которого есть свои прелести.
Ответ 2
К сожалению, вы не можете генерировать константы NSNumber
так же, как вы можете генерировать константы NSString
. Когда вы попытаетесь сделать это, вы получите ошибку компилятора
NSNumber * const kNumberConstant = @2; // This doesn't work.
Однако вместо этого вы можете использовать примитивы.
NSInteger const kSomeIntValue = 10;
Ответ 3
В основном вы можете достичь того, чего хотите в трех частях:
.h файл:
extern NSNumber *MyFirstConstant;
.m file
NSNumber *MyFirstConstant;
AppDelegate.m
+(void)initialize
{
MyFirstConstant = @5;
...
}
AppDelegate гарантированно запускается перед любым другим вашим кодом, а инициализация - это первый метод, который будет вызываться в AppDelegate, поэтому вы можете по существу застраховать все свои константы для вас перед запуском приложения.
Ответ 4
обновление:
Спустя годы я просто понял, что можно создать константу NSNumber для целых чисел... но это взломать:
#define CONST_INT_NSNUMBER( x ) ((__bridge NSNumber * const)(void * const)(( x << 8 ) | 0x27))
NSNumber * const number = CONST_INT_NSNUMBER(123) ;
Это работает, потому что некоторые целочисленные NSNumbers хранятся как тегированные указатели.
оригинальный ответ:
Вы не можете этого сделать.
NSNumber * const mynumber = @5.5;
дает:
Элемент инициализатора не является константой времени компиляции
Предположим, что у компилятора есть специальная функция, специально предназначенная для создания констант NSString
постоянной компиляции, но не любого другого типа объекта.
Вы могли бы сделать это, однако:
.h
extern NSNumber * kConstantNumber ;
ого
NSNumber * kConstantNumber ;
@implementation NSNumber (InitializeConstants)
+(void)load
{
kConstantNumber = @42;
// ... and the rest ...
}
@end