18

我想通过本主题中用于 NSStrings 的相同样式制作一些 NSNumber 常量。也就是说,我正在创建单独的 constants.h/.m 文件并将它们导入到需要访问它们的类中。

4

4 回答 4

18

这样做的问题是没有编译时常量 NSNumber 这样的东西。只有 NSString 获得了这种区别。NSNumbers 总是动态创建的。您可以使用在程序启动时运行的函数来初始化变量来伪造它。您的选择:

  1. +load使用执行初始化的方法创建一个类。

  2. 在包含常量的文件中,包含一个带有__attribute__((constructor)). 因此,例如:

    // Constants.m
    
    NSNumber *someGlobalNumber;
    
    __attribute__((constructor))
    static void InitGlobalNumber() {
        someGlobalNumber = [[NSNumber numberWithInteger:1] retain];
    }
    

但是,当然,您不能在启动过程早期运行的任何其他功能中可靠地使用这些数字。这通常不是问题,但值得牢记。

另一个选项,我见过几次,是有一个带有数字访问器的类,而不是提供对变量的原始访问。这是一个更重的设计,但它也感觉不那么巫毒,这有它的魅力。

于 2012-09-04T18:08:34.227 回答
16

不幸的是,您目前无法像生成NSNumber常量一样生成NSString常量。当你尝试这样做时,你会得到一个编译器错误

NSNumber * const kNumberConstant = @2; // This doesn't work.

但是,您可以改用原语。

NSInteger const kSomeIntValue = 10;
于 2012-09-04T18:04:14.907 回答
5

您基本上可以在三个部分中实现接近您想要的效果:

.h 文件:

extern NSNumber *MyFirstConstant;

.m 文件

NSNumber *MyFirstConstant;

AppDelegate.m

+(void)initialize
{
    MyFirstConstant = @5;
    ...
}

AppDelegate 保证在您的任何其他代码之前运行,并且初始化是在 AppDelegate 上调用的第一个方法,因此您基本上可以确保在您的应用程序运行之前为您设置所有常量。

于 2012-09-04T19:37:52.600 回答
4

更新:

多年后,我才意识到可以整数创建一个 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
于 2012-09-04T18:06:28.027 回答