类型和声明
方法声明
如示例所示,@interface 声明中推荐的声明顺序是:属性(Property)、类方法(Class Method)、初始化方法(Initializer),最后是实例方法(Instance Method)。类方法部分应以便捷构造方法(Convenience Constructor)开头。
局部变量
在尽可能窄的实际作用域中声明变量,并在靠近使用处声明。在声明时初始化变量。
// GOOD:
CLLocation *location = [self lastKnownLocation];
for (int meters = 1; meters < 10; meters++) {
reportFrogsWithinRadius(location, meters);
}有时,效率方面的考虑会使在其使用作用域之外声明变量更为合适。此示例将 meters 与初始化分开声明,并在每次循环中不必要地发送 lastKnownLocation 消息:
// AVOID:
int meters; // AVOID.
for (meters = 1; meters < 10; meters++) {
CLLocation *location = [self lastKnownLocation]; // AVOID.
reportFrogsWithinRadius(location, meters);
}在自动引用计数(Automatic Reference Counting, ARC)下,指向 Objective-C 对象的强引用和弱引用指针会自动初始化为 nil,因此对于这些常见情况不需要显式初始化为 nil。但是,自动初始化不会发生在许多 Objective-C 指针类型上,包括使用 __unsafe_unretained 所有权限定符声明的对象指针和 CoreFoundation 对象指针类型。如有疑问,最好初始化所有 Objective-C 局部变量。
静态变量
当实现文件中的文件作用域变量/常量声明不需要在该文件外部引用时,将它们声明为 static(或在 Objective-C++ 中放入匿名命名空间(Anonymous Namespace))。不要在 .h 文件中声明具有静态存储持续时间的文件作用域变量或常量(或在 Objective-C++ 中放入匿名命名空间)。
// GOOD:
// 文件: Foo.m
static const int FOORequestLimit = 5;// AVOID:
// 文件: Foo.h
static const int FOORequestLimit = 5; // AVOID.无符号整数
除非匹配系统接口使用的类型,否则避免使用无符号整数。
使用无符号整数进行数学运算或倒数到零时会出现微妙的错误。除非匹配系统接口中的 NSUInteger,否则在数学表达式中仅依赖有符号整数。
// GOOD:
NSUInteger numberOfObjects = array.count;
for (NSInteger counter = numberOfObjects - 1; counter >= 0; --counter)// AVOID:
for (NSUInteger counter = numberOfObjects - 1; counter >= 0; --counter) // AVOID.无符号整数可用于标志位(Flags)和位掩码(Bitmasks),不过通常 NS_OPTIONS 或 NS_ENUM 会更合适。
大小不一致的类型
请注意,long、NSInteger、NSUInteger 和 CGFloat 类型的大小在 32 位和 64 位构建中有所不同。当匹配系统接口时使用它们是合适的,但在处理需要精确大小的 API 时应避免使用,例如 proto API。
// GOOD:
int32_t scalar1 = proto.intValue;
int64_t scalar2 = proto.longValue;
NSUInteger numberOfObjects = array.count;
CGFloat offset = view.bounds.origin.x;// AVOID:
NSInteger scalar2 = proto.longValue; // AVOID.文件和缓冲区大小通常超过 32 位限制,因此应使用 int64_t 声明,而不是使用 long、NSInteger 或 NSUInteger。
浮点常量
定义 CGFloat 常量时,请注意以下事项。
以前,对于面向 32 位平台的项目,使用 float 字面量(带 f 后缀的数字)可能是避免类型转换警告所必需的。
由于所有 Google iOS 项目现在仅面向 64 位运行时,CGFloat 常量可以省略后缀(使用 double 值)。不过,团队可以选择为了遗留代码的一致性继续使用 float 数字,直到最终全面迁移到 double 值。避免在同一代码中混合使用 float 和 double 值。
// GOOD:
// 好的,因为 CGFloat 是 double
static const CGFloat kHorizontalMargin = 8.0;
static const CGFloat kVerticalMargin = 12.0;
// 只要项目中所有 CGFloat 常量的值都是 float,这也是可以的
static const CGFloat kHorizontalMargin = 8.0f;
static const CGFloat kVerticalMargin = 12.0f;// AVOID:
// 避免混合使用 float 和 double 常量
static const CGFloat kHorizontalMargin = 8.0f;
static const CGFloat kVerticalMargin = 12.0;