Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reasons to use NSString constants over enums?

I'm wondering why Apple is using (quite heavily in CoreAnimation, but elsewhere too) constants that are declared as NSString * const like for example kCAGravityTop instead of regular enums? How about type safety in this case? As I understand it, one could pass any NSString to a method expecting this constant without getting any compiler warnings.

like image 765
esad Avatar asked Aug 19 '09 20:08

esad


4 Answers

I'm not sure, but I'm guessing it has to do with users adding their own extensions and subclasses to some of the Apple stuff. In that case, you can just override the used method and catch the case where the string is "MyOwnValue" and then do whatever you want with it. This is significantly easier than having to modify Apple's enum, and it also keeps you from screwing anything up.

It also might be for making it easier for Apple to have version independence. With enums, if you rearrange their order in some way it can cause a lot of problems for any of their values that have been cached (for whatever reason). If the enum's value is 1 << 3 when it is saved to a file, then Apple adds another enum in so that its value is now 1 << 4, then obviously the wrong thing is coming out of your program. Why wouldn't they just be careful about moving enum values around, I don't know, but I think it's definitely likely that they used NSString because there's no way its value or ordering can be changed across any version.

like image 157
Eli Avatar answered Nov 18 '22 07:11

Eli


Enumerated types can't be extended without adding additional entries within the enumerated type itself. Thus, it is impossible to have enumeration contents that are both treated both as a formal member of the enumerated type, yet are also not visible during normal compilation.

Take CoreAnimation, for example. There may be values that are used internally that are not supported or made available via the public API for a variety of reasons; "implementation detail" immediately comes to mind.

Beyond that, strings as constants enable extension as Eli implies. They also tend to be much more informative when debugging. "kCAGravityTop" is much more indicative than, say, "4".

In terms of performance, there is very little penalty to using strings. Static strings, of which the internal counterpart to every external declaration of just about every string constant is actually composed of, are handled efficiently by the compiler and the -isEqualToString: method's first test is pointer equality -- very fast. Not quite as fast as a switch(), but given the magnitude of code execution implied by the constant, the few cycles difference between switch() and string comparison is irrelevant.

like image 20
bbum Avatar answered Nov 18 '22 05:11

bbum


I suspect that the reason is historical or stylistic more than anything else. This is how the NeXT frameworks did it and that created the Cocoa "style". As a benefit of this approach, inspecting the value in the debugger can give a meaningful value (e.g. @"CAGravityTop" or something like that instead of a meaningless int). Because static strings are handled intelligently by the compiler, comparison can be by pointer comparison rather than string equality (see bbum's answer), so there's negligible performance hit for this approach.

like image 7
Barry Wark Avatar answered Nov 18 '22 06:11

Barry Wark


One more reason I thought of in favour of NSString is that it can passed around wherever id is accepted (such as userInfo or as dictionary keys) while primitive types (enums) would need some kind of wrapper for this

like image 5
esad Avatar answered Nov 18 '22 07:11

esad