我想通过本主题中用于 NSStrings 的相同样式制作一些 NSNumber 常量。也就是说,我正在创建单独的 constants.h/.m 文件并将它们导入到需要访问它们的类中。
4 回答
这样做的问题是没有编译时常量 NSNumber 这样的东西。只有 NSString 获得了这种区别。NSNumbers 总是动态创建的。您可以使用在程序启动时运行的函数来初始化变量来伪造它。您的选择:
+load
使用执行初始化的方法创建一个类。在包含常量的文件中,包含一个带有
__attribute__((constructor))
. 因此,例如:// Constants.m NSNumber *someGlobalNumber; __attribute__((constructor)) static void InitGlobalNumber() { someGlobalNumber = [[NSNumber numberWithInteger:1] retain]; }
但是,当然,您不能在启动过程早期运行的任何其他功能中可靠地使用这些数字。这通常不是问题,但值得牢记。
另一个选项,我见过几次,是有一个带有数字访问器的类,而不是提供对变量的原始访问。这是一个更重的设计,但它也感觉不那么巫毒,这有它的魅力。
不幸的是,您目前无法像生成NSNumber
常量一样生成NSString
常量。当你尝试这样做时,你会得到一个编译器错误
NSNumber * const kNumberConstant = @2; // This doesn't work.
但是,您可以改用原语。
NSInteger const kSomeIntValue = 10;
您基本上可以在三个部分中实现接近您想要的效果:
.h 文件:
extern NSNumber *MyFirstConstant;
.m 文件
NSNumber *MyFirstConstant;
AppDelegate.m
+(void)initialize
{
MyFirstConstant = @5;
...
}
AppDelegate 保证在您的任何其他代码之前运行,并且初始化是在 AppDelegate 上调用的第一个方法,因此您基本上可以确保在您的应用程序运行之前为您设置所有常量。
更新:
多年后,我才意识到可以为整数创建一个 NSNumber 常量......但这是一个 hack:
#define CONST_INT_NSNUMBER( x ) ((__bridge NSNumber * const)(void * const)(( x << 8 ) | 0x27))
NSNumber * const number = CONST_INT_NSNUMBER(123) ;
这是因为某些整数 NSNumber 被存储为标记指针。
原答案:
你不能这样做。
NSNumber * const mynumber = @5.5;
给出:
Initializer 元素不是编译时常量
暗示编译器具有专门用于创建编译时常NSString
量对象的特殊功能,但没有任何其他类型的对象。
但是,您可以这样做:
.h:
extern NSNumber * kConstantNumber ;
.m:
NSNumber * kConstantNumber ;
@implementation NSNumber (InitializeConstants)
+(void)load
{
kConstantNumber = @42;
// ... and the rest ...
}
@end