第一行是编译时常量,因为您正在分配@"a"
而不是类似的东西static NSString *a = [NSString stringWithFormat:@"a"];
(这将引发相同的错误)
但对于一个NSNumber
,static NSNumber *b = @1;
其实就等价于static NSNumber *b = [NSNumber numberWithInt:1];
。有关更多详细信息,请查看 Objective-C 文字。
请注意,在上述情况下,右侧不是编译时常量。它是一个必须在运行时计算的表达式。在 C 和 Objective-C 中,静态变量必须使用编译时常量进行初始化。
如果你想NSNumber
作为一个const
你可以检查这里提到的方法Objective C - How to use extern variables?.
还要检查来自 Mike Ash 的 Objective C 文字,
重要的是要注意,新的文字语法都不能作为编译时常量。
和,
由于编译器和库之间的紧密耦合,NSString 文字也是编译时常量。有一个名为 NSConstantString 的特殊 NSString 子类,具有固定的 ivar 布局:
这种紧密耦合具有优势,例如生成合法的全局变量初始化器,并且不需要额外的代码来运行以在运行时构建对象。但是,也有很大的缺点。NSConstantString 布局是永久设置的。该类必须完全使用该数据布局来维护,因为该数据布局已融入数千个第三方应用程序。如果 Apple 更改布局,那些第三方应用程序就会崩溃,因为它们包含具有旧布局的 NSConstantString 对象。
如果 NSArray 字面量是编译时常量,则需要有一个类似的 NSConstantArray 类,它具有编译器可以生成的固定布局,并且必须与其他 NSArray 实现分开维护。这样的代码不能在没有这个 NSConstantArray 类的旧操作系统上运行。新文字可以产生的其他类也存在同样的问题。
这在 NSNumber 文字的情况下特别有趣。Lion 引入了标记指针,它允许将 NSNumber 的内容直接嵌入到指针中,从而无需单独的动态分配对象。如果编译器发出标记指针,它们的格式永远不会改变,并且与旧操作系统版本的兼容性将丢失。如果编译器发出常量 NSNumber 对象,那么 NSNumber 文字将与其他 NSNumber 有很大不同,可能会对性能造成重大影响。
相反,编译器只是简单地向框架发出调用,完全像您手动完成的那样构造对象。这会导致一些运行时问题,但并不比在没有新语法的情况下自己构建它们更糟糕,并且使设计更加简洁。