Why NSNumber literals cannot be used in static declarations

I declare:

static NSString *a = @"a"; 

and this is the correct declaration in iOS6 (it’s more correct to use the compiler version, but at the moment I don’t know). I thought with numeric literals as well:

 static NSNumber * b=@1 ; 

may be a valid ad. The compiler tells me that initializer element is not a compile time constant . It surprises me a bit. Since NSNumber immutable as NSString , and since I use a literal, as in the string case, I thought it could also be valid.

Does anyone have a reasonable explanation for this difference?

+6
source share
1 answer

The first line is a compile-time constant, since you assign @"a" , not something like static NSString *a = [NSString stringWithFormat:@"a"]; (this will result in the same error)

But for NSNumber , static NSNumber *b = @1; actually equivalent to static NSNumber *b = [NSNumber numberWithInt:1]; . For more information check out Objective-C literals .

Note that in the above case, the right side is not a compile time constant. This is an expression that must be evaluated at runtime. In C and Objective-C, static variables must be initialized with compile-time constants.

If you want to have NSNumber as const , you can check with the Objective-C approaches mentioned here - How to use external variables? .

Also check this out on Mike Ash's Objective-C literals ,

It is important to note that not one of the syntaxes of the new literal qualifies as a compile-time constant.

and

NSString literals are also compile-time constants since there is a link between the compiler and the libraries. There, a special NSString Subclass is called NSConstantString with a fixed ivar location:

This hard connection has advantages such as producing legal variable initializers and does not require additional code to run the object at runtime. However, there are big disadvantages. The NSConstantString layout is set forever. This class must be supported with exactly this data composition, as this data layout is baked into thousands of third-party applications. If Apple changes the layout, those third-party applications will break because they contain NSConstantString objects with the old location.

If the NSArray literals were compile-time constants, it would be necessary to be a similar NSConstantArray class with a fixed layout that the compiler could generate, and this would need to be maintained separately from other NSArray implementations. Such code could not work on older operating systems that did not have this class NSConstantArray. The same problem exists for other classes that may have new literals to produce.

This is especially interesting with NSNumber literals. Leo introduced tagged pointers that allow NSNumber to be embedded directly in the pointer, eliminating the need for a separate, dynamically allocated object. If the compiler has issued tagged pointers, their format can never change, and compatibility with old OS releases will be lost. If the compiler emits a constant NSNumber of objects, then the NSNumber literals will be significantly different from other NSNumbers, with possible significant success.

Instead, the compiler simply emits calls into the framework, constructing the objects in exactly the same way as you would do manually. This leads to some hit at runtime, but they are no worse than building themselves without a new syntax and make a much cleaner design.

+16
source

All Articles