在Objective-C中定义表单
有什么区别
typedef enum { ... } Name;
和
enum { ... }; typedef NSUInteger Name;
? 如果function相同,那么第二种forms有什么好处呢? 这不是不必要的混乱吗?
enum
和C
一样古老,因此是Objective-C
的一部分。 这只是一个int
types的显式编码。 这对debugging非常有用,大多数较新的编译器可以基于它进行优化。 (你应该完全忽略)。 这对于提高代码的可读性是最有用的(对任何人来说,或者在你睡觉之后给自己)。
typedef enum { ... } NameType ;
随之而来
NameType name;
这通常是typedef的首选风格,
你的第二个例子不会将typedef与你想要指定的值只绑定给定的types。
请注意,这并不妨碍您执行
name = 10244; // some non-valid value not listed in the enumeration
但是有些编译器在这种情况下可能会产生警告,
今天我碰到苹果使用以下内容:
enum { NSFetchedResultsChangeInsert = 1, NSFetchedResultsChangeDelete = 2, NSFetchedResultsChangeMove = 3, NSFetchedResultsChangeUpdate = 4 }; typedef NSUInteger NSFetchedResultsChangeType;
他们这样做是因为他们真的希望NSFetchedResultsChangeType
是它们定义为NSUInteger
的types。 这可以是一个int
但也可以是别的东西。 而值1,2,3和4,这与我们的types有些不相干。 但是他们正在编写一个不同的抽象层次,因为他们是一个工具提供者。
你不应该看苹果的编码风格提示。 如果你看到的东西看起来更清洁/更好的编码方式,通常是这样。 正如凯文所说,API的稳定性对他们来说是至关重要的。
编辑(2013年1月)如果您有权访问WWDC 2012会话video,则应该观看Session 405 - Modern Objective-C
-6:00-10:00。 在较新的编译器中讨论了一种新的语法,它允许明确地确定types的大小,并将值紧密地绑定到types上。 (借用C ++ 11)
enum NSFetchedResultsChangeType : NSUInteger { NSFetchedResultsChangeInsert = 1, NSFetchedResultsChangeDelete = 2, NSFetchedResultsChangeMove = 3, NSFetchedResultsChangeUpdate = 4 };
前者定义了一个types名称来引用一个枚举。 这是大多数枚举用C命名的方式。后者虽然有点不同,并且在Cocoa框架中很普遍。 有两个理由使用后者。 首先是如果你的枚举定义了一个位域,并且你想在这里,因为当你提供一个“名称”值,你会提供一个枚举值的组合。 换句话说,如果你这样说
[self doSomethingWithBitfield:(Enum1 | Enum2)]
你没有传递一个Name的值,而是一个二者结合的整数。
然而,Cocoa框架甚至为非bitfield值使用这个习惯用法,这是一个很好的原因:API的稳定性。 根据C标准,枚举的底层整型需要能够包含枚举中的所有值,但是由编译器另外select。 这意味着添加一个新的枚举值可以改变枚举的整数types(例如,加-1可以使它被签名,增加60亿可以使它变成很长的等等)。 从API稳定性的angular度来看,这是一件坏事,因为采用此枚举值的方法的types编码可能会意外更改,并有可能破坏现有的代码和二进制文件。 为了防止这种情况,Cocoa框架通常将types定义为NSUInteger(或NSInteger,如果它们需要负数),所以API和types编码保持稳定。