我想通过this topic中用于NSStrings的相同样式制作一些NSNumber常量。也就是说,我正在创建单独的constants.h / .m文件并将它们导入需要访问它们的类中。
答案 0 :(得分:18)
这样做的麻烦在于没有编译时常量NSNumber这样的东西。只有NSString才能获得这种区别。 NSNumbers始终是动态创建的。您可以使用在程序启动时运行的函数来伪造它以初始化变量。你的选择:
使用+load
方法创建一个执行初始化的类。
在包含常量的文件中,包含一个__attribute__((constructor))
的函数。所以,例如:
// Constants.m
NSNumber *someGlobalNumber;
__attribute__((constructor))
static void InitGlobalNumber() {
someGlobalNumber = [[NSNumber numberWithInteger:1] retain];
}
但是当然,您无法在启动过程早期运行的任何其他功能中可靠地使用这些数字。这通常不是问题,但值得记住。
另一个选项,我已经看过几次,是为了让一个类具有数字访问器,而不是给变量提供原始访问权限。这是一个更重的设计,但它也感觉不那么巫术,它有它的魅力。
答案 1 :(得分:16)
不幸的是,您当前无法生成NSNumber
常量,就像生成NSString
常量一样。当您尝试这样做时,您将收到编译器错误
NSNumber * const kNumberConstant = @2; // This doesn't work.
但是,您可以使用原语。
NSInteger const kSomeIntValue = 10;
答案 2 :(得分:5)
你基本上可以在三个方面达到你想要的效果:
.h文件:
extern NSNumber *MyFirstConstant;
.m文件
NSNumber *MyFirstConstant;
AppDelegate.m
+(void)initialize
{
MyFirstConstant = @5;
...
}
AppDelegate保证在您的任何其他代码之前运行,并且初始化是在AppDelegate上调用的第一个方法,因此您可以基本上确保在应用程序运行之前为您设置所有常量。
答案 3 :(得分:4)
多年以后,我才意识到 可以为整数创建一个NSNumber常量......但这是一个黑客攻击:
#define CONST_INT_NSNUMBER( x ) ((__bridge NSNumber * const)(void * const)(( x << 8 ) | 0x27))
NSNumber * const number = CONST_INT_NSNUMBER(123) ;
这是有效的,因为某些整数NSNumber存储为tagged pointers。
你不能这样做。
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