C 语言特性
宏
避免使用宏(Macro),特别是在可以使用 const 变量、枚举、Xcode 代码片段或 C 函数代替的情况下。
宏使你看到的代码与编译器看到的代码不同。现代 C 使得传统上使用宏来定义常量和工具函数变得不必要。宏仅应在没有其他可用解决方案时使用。
当需要使用宏时,使用唯一的名称以避免编译单元中符号冲突的风险。如果可行,在使用后通过 #undefining 来限制宏的作用域。
宏名称应使用 SHOUTY_SNAKE_CASE——全部大写字母,单词之间用下划线分隔。函数式宏(Function-like Macro)可以使用 C 函数命名惯例。不要定义看起来像 C 或 Objective-C 关键字的宏。
// GOOD:
#define GTM_EXPERIMENTAL_BUILD ... // GOOD
// 除非 X > Y 否则断言
#define GTM_ASSERT_GT(X, Y) ... // GOOD, 宏风格。
// 除非 X > Y 否则断言
#define GTMAssertGreaterThan(X, Y) ... // GOOD, 函数风格。// AVOID:
#define kIsExperimentalBuild ... // AVOID
#define unless(X) if(!(X)) // AVOID避免展开为不平衡的 C 或 Objective-C 结构的宏。避免引入作用域或可能混淆块(Block)中值捕获的宏。
避免在头文件中生成类、属性或方法定义作为公共 API 的宏。这些只会使代码难以理解,而语言本身已经有更好的方式来实现这一点。
避免生成方法实现的宏,或生成稍后在宏外部使用的变量声明的宏。宏不应通过隐藏变量声明的位置和方式来使代码难以理解。
// AVOID:
#define ARRAY_ADDER(CLASS) \
-(void)add ## CLASS ## :(CLASS *)obj toArray:(NSMutableArray *)array
ARRAY_ADDER(NSString) {
if (array.count > 5) { // AVOID -- 'array' 在哪里定义的?
...
}
}可接受的宏使用示例包括基于构建设置条件编译的断言和调试日志宏——通常这些不会编译到发布版本中。
非标准扩展
除非另有规定,否则不得使用 C/Objective-C 的非标准扩展。
编译器支持各种不属于标准 C 的扩展。示例包括复合语句表达式(Compound Statement Expression)(例如 foo = ({ int x; Bar(&x); x }))。
__typeof__ 关键字
在类型不能为读者提供清晰度的情况下,允许使用 __typeof__ 关键字。鼓励使用 __typeof__ 关键字而非其他类似关键字(如 typeof 关键字),因为它在所有语言变体中都受支持。
// GOOD:
__weak __typeof__(self) weakSelf = self;// AVOID:
__typeof__(data) copiedData = [data copy]; // AVOID.
__weak typeof(self) weakSelf = self; // AVOID.__auto_type 关键字和类型推导
使用 __auto_type 关键字的类型推导(Type Deduction)仅允许用于块(Block)和函数指针(Function Pointer)类型的局部变量。如果块或指针类型已有 typedef,则避免使用类型推导。
// GOOD:
__auto_type block = ^(NSString *arg1, int arg2) { ... };
__auto_type functionPointer = &MyFunction;
typedef void(^SignInCallback)(Identity *, NSError *);
SignInCallback signInCallback = ^(Identity *identity, NSError *error) { ... };// AVOID:
__auto_type button = [self createButtonForInfo:info];
__auto_type viewController = [[MyCustomViewControllerClass alloc] initWith...];
typedef void(^SignInCallback)(Identity *, NSError *);
__auto_type signInCallback = ^(Identity *identity, NSError *error) { ... };已批准的非标准扩展
__attribute__关键字是被批准的,因为它在 Apple API 声明中使用。- 条件运算符的二元形式
A ?: B是被批准的。