为什么NSNumber文字不能用于静态声明

时间:2012-12-13 23:12:31

标签: objective-c ios static ios6 nsnumber

我宣布:

static NSString *a = @"a";

这是iOS6中的正确声明(使用编译器版本应该更正确,但目前我还不知道)。我还想到了数字文字:

static NSNumber *b=@1;

可能是有效的声明。编译器告诉我initializer element is not a compile time constant。这让我感到惊讶。由于NSNumber不可变为NSString,并且由于我在字符串情况下使用文字,因此我认为它也可以是有效的。

有没有人对这种差异有合理的解释?

1 个答案:

答案 0 :(得分:17)

第一行是编译时常量,因为你分配@"a"而不是像static NSString *a = [NSString stringWithFormat:@"a"];那样(这会抛出相同的错误)

但对于NSNumberstatic NSNumber *b = @1;实际上等同于static NSNumber *b = [NSNumber numberWithInt:1];。有关详细信息check Objective-C Literals.

请注意,在上述情况下,右侧不是编译时常量。它是一个必须在运行时计算的表达式。在C和Objective-C中,必须使用编译时常量初始化静态变量。

如果您想NSNumber作为const,可以查看此处提到的方法Objective C - How to use extern variables?

另外check this on Objective C literals from Mike Ash

  

重要的是要注意,没有新的文字语法符合条件   作为编译时常量。

  

NSString文字也是编译时常量,因为它很紧   编译器和库之间的耦合。有一个特别的   NSString子类名为NSConstantString,具有固定的ivar布局:

     

这种紧密耦合具有优势,例如产生合法的全球性   变量初始化器,并且不需要运行额外的代码来构建   对象在运行时。但是,也存在很大的缺点。该   NSConstantString布局永远设置。必须保持这一课程   正是这种数据布局,因为数据布局被烘焙成   成千上万的第三方应用程序。如果Apple改变了布局,那些   第三方应用程序会破坏,因为它们包含NSConstantString   具有旧布局的对象。

     

如果NSArray文字是编译时常量,则需要   是一个类似的NSConstantArray类,具有固定的布局   编译器可以生成,并且必须维护   与其他NSArray实现分开。这样的代码无法运行   在没有此NSConstantArray类的旧操作系统上。相同   新文字可以存在的其他类存在问题   产生

     

在NSNumber文字的情况下,这一点特别有趣。   Lion引入了标记指针,允许NSNumber的内容   直接嵌入指针,无需a   分离动态分配的对象。如果编译器发出标记   指针,它们的格式永远不会改变,并且与旧的兼容性   操作系统版本将丢失。如果编译器发出恒定的NSNumber   对象,然后NSNumber文字将大不相同   其他NSNumbers,可能会有重大的性能影响。

     

相反,编译器只是向框架发出调用,   完全像手动完成的那样构造对象。   这会导致一点运行时命中,但不会比构建更糟糕   他们自己没有新的语法,并使一个更清洁   设计。