在枚举上使用NSString常量的原因?

esa*_*sad 7 coding-style objective-c

我想知道为什么Apple使用(在CoreAnimation中相当多,但在其他地方也是如此)常量被声明NSString * const为例如kCAGravityTop而不是常规枚举?在这种情况下类型安全怎么样?据我所知,可以将任何NSString传递给期望此常量的方法,而不会收到任何编译器警告.

Eli*_*Eli 11

我不确定,但我猜这与用户在某些Apple内容中添加自己的扩展和子类有关.在这种情况下,您可以覆盖已使用的方法并捕获字符串为"MyOwnValue"的情况,然后随意执行任何操作.这比修改Apple的枚举要容易得多,它也可以防止你搞砸任何东西.

它也可能是为了让Apple更容易拥有版本独立性.使用枚举,如果你以某种方式重新排列它们的顺序,它可能会导致很多问题,因为它们的任何值都已被缓存(无论出于何种原因).如果enum的值在保存到文件时为1 << 3,那么Apple会添加另一个枚举,使其值现在为1 << 4,那么显然错误的是你的程序出来了.为什么他们不会小心移动枚举值,我不知道,但我认为他们肯定可能使用NSString,因为它的价值或排序无法在任何版本中更改.


bbu*_*bum 9

如果不在枚举类型本身中添加其他条目,则无法扩展枚举类型.因此,枚举内容既不能作为枚举类型的正式成员,也不能在正常编译期间看不到,也是不可能的.

以CoreAnimation为例.由于各种原因,可能存在内部使用的值,这些值不受支持或通过公共API提供; 马上就会想到"实施细节".

除此之外,字符串作为常量可以实现Eli所暗示的扩展.调试时,它们也往往提供更多信息."kCAGravityTop"比"4"更具指示性.

在性能方面,使用字符串的惩罚很小.静态字符串,其中几乎每个字符串常量的每个外部声明的内部对应实际上由编译器组成,并且-isEqualToString:方法的第一个测试是指针相等 - 非常快.不如switch()快,但考虑到常量隐含的代码执行幅度,switch()和字符串比较之间的几个周期差异是无关紧要的.


Bar*_*ark 7

我怀疑其原因是历史或风格,而不是其他任何东西.这就是NeXT框架如何做到这一点,并创造了Cocoa"风格".作为这种方法的一个好处,检查调试器中的值可以给出一个有意义的值(例如@"CAGravityTop"或类似的东西,而不是无意义的int).因为静态字符串是由编译器智能处理的,所以比较可以通过指针比较而不是字符串相等(参见bbum的答案),因此这种方法的性能损失可以忽略不计.


esa*_*sad 5

我认为支持NSString的另一个原因是它可以在任何id被接受的地方传递(例如userInfo或作为字典键),而原始类型(枚举)需要某种类型的包装器