在Objective-C中定义表单

有什么区别

typedef enum { ... } Name; 

 enum { ... }; typedef NSUInteger Name; 

? 如果function相同,那么第二种forms有什么好处呢? 这不是不必要的混乱吗?

enumC一样古老,因此是Objective-C的一部分。 这只是一个inttypes的显式编码。 这对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编码保持稳定。