这是我为团队制定的 iOS 代码规范,供大家参考。
文档说明
Version |
Time |
Author |
0.1 Alpha |
2014-08-21 |
StoneArk |
0.2 Beta |
2014-09-02 |
StoneArk |
0.3 Beta |
2014-09-15 |
StoneArk |
1.0 |
2014-09-16 |
StoneArk |
基本原则
求同存异。
合理的编码风格不只一个,尊重每位开发人员的编码习惯。但不合理的编码习惯必须避免。
命名规则
范围 |
命名规则 |
示例 |
变量名、方法名 |
驼峰式命名 (小驼峰式命名) |
onlineCount - (void)viewDidLoad |
类名、枚举类型名 |
Pascal 命名 |
MainViewController FruitType |
常量 |
全部大写或k开头的驼峰式命名 |
FONTNAME kFontName |
宏定义 |
全部大写 |
LOCALDEBUG |
枚举值 |
要有枚举类型前缀 |
FruitType 枚举类型的枚举值应为 FruitTypeApple , FruitTypeBanana 等 |
范围 |
命名约定 |
示例 |
数组 |
arr... ...Array |
arrImage imageArray |
字符串 |
str... ...String |
strTitle titleString |
布尔变量 |
is... |
isShown |
按钮 |
btn... ...Button |
btnSubmit submitButton |
标签 |
lbl... ...Label |
lblTitle titleLabel |
滚动视图 |
scrView... ...ScrollView |
scrViewContent contentScrollView |
按钮点击 |
btn...Click ...Action |
- (void)btnSubmitClick - (void)submitAction |
- 注意
- 应为有意义的命名,除循环变量外,不得使用
i
, j
, k
等单字符作为名称。
- 不得使用关键字、保留字命名,如
id
, const
, bool
等。
- 尽可能地避免出现魔术数字,应采用枚举类型、 常量、宏定义等方式赋予数字以具体意义。
- 除非必要(如名称过长或已为众所周知的缩写),命名不应使用缩写。
- 除非必要(如特定名称或没有合适的单词),命名应采用规范的英文单词,避免采用汉语拼音。
代码缩进
基本要求
所有代码必须有符合其层次结构的缩进,缩进使用 4 个空格符。
大括号的处理
(1)允许的形式有 K&R、Allman Style、1TBS。
示例:
1 2 3 4 5 6 7 8 9
| // K&R - (void)functionExample { if (YES){ ... } else { ... } }
|
1 2 3 4 5 6 7 8 9 10 11 12
| // Allman Style - (void)functionExample { if (YES) { ... } else { ... } }
|
主要注意点:
a. 对于函数
开括号应在下一行中独占一行,并与开头行有相同的缩进。括号内的语句应该缩进。闭括号应单独占一行,并与开头行有相同的缩进。
b. 对于函数内的控制语句块
(K&R, 1TBS)开括号应与控制语句在同一行中,闭括号单独占一行(除非有 else 或 while 关键字),并与开头行有相同的缩进。<br />
(Allman Style)与函数一致,开括号也应独占一行。
c. 如果控制语句块内只有一条语句
(1TBS)不能省略括号。<br />
(K&R)可以省略括号(强烈不推荐,很容易产生逻辑错误,如著名的苹果 gotofail bug)。<br />
(2)不允许 的大括号缩进方式
a.闭括号不独占一行
1 2
| - (void)functionExample{ if (YES){...}}
|
b.括号层次对应关系不正确
1 2 3 4 5 6 7
| - (void)functionExample { if (YES) { ... } }
|
自动化工具
- 简单地调整代码缩进,可运用 Xcode 的 Re-Indent,快捷键 ⌃I。
- 更复杂地调整代码格式,可使用 Uncrustify 等工具进行自动化调整。
注释规范
注释范围及内容
- 对于每一个类,必须 在头文件中为其添加类注释。
- 对于类的公有属性,必须 在头文件中为其添加属性注释。
- 对于类的公有方法,必须 在头文件中为其添加方法注释。
- 对于不含有任何类的头文件,必须 在头文件中为其添加头文件注释。
- 对于周知的方法,如常用控件的代理方法、SDK 中提供的方法等,不必添加注释(除非必要)。
- 对于需要暂时屏蔽的代码(段),可通过注释的形式进行屏蔽。
- 对于确定无用或已废弃的代码(段),不应以注释的形式存在于工程中。
注意事项
- 注释要用正确、清晰、符合语法的中文或英文书写。
- 注释怕短不怕长。注释要详尽地反映代码(段)的业务意义或逻辑意义。
- 注释不是对语法的解释,千万不要写这种注释,这种注释是无效且无用的:
一般注释形式
通常,超过 5 行的注释不应采用单行注释,应采用多行注释。
或
1 2 3 4
| /* * 注释内容1 * 注释内容2 */
|
1 2 3 4 5
| // Start: 代码段简介 firstLine; ... lastLine; // End: 代码段简介
|
关键注释形式
按照 HeaderDoc 标签规范书写。
1 2 3 4 5
| /*! * 类描述 */ @interface ExampleClass : NSObject { }
|
1 2 3
| /// 类描述 @interface ExampleClass : NSObject { }
|
1 2 3 4 5
| /*! * @brief 属性简介 * @discussion 属性详细描述 */ @property (strong, nonatomic) NSString *strExample;
|
1 2
| /// 属性简介 @property (strong, nonatomic) NSString *strExample;
|
其中,@discussion 标签为可选项。
简单方法:
1 2 3 4
| /*! * @brief 方法简介 */ - (void)simpleMethod;
|
1 2
| /// 方法简介 - (void)simpleMethod;
|
含有参数和返回值的方法:
1 2 3 4 5 6 7 8 9
| /*! * @brief 方法简介 * * @param para1 参数一描述 * @param para2 参数二描述 * * @return 返回结果描述 */ - (BOOL)exampleMethodWithPara:(NSString*)para1 anotherPara:(NSString*)para2;
|
更为复杂的方式:
1 2 3 4 5 6 7 8 9
| /*! * @brief 方法简介 * @discussion 方法具体描述 * @param para1 参数一描述 * @param para2 参数二描述 * @return 返回结果描述 * @warning 注意事项 */ - (BOOL)exampleMethodWithPara:(NSString*)para1 anotherPara:(NSString*)para2;
|
1 2 3 4 5
| /*! * @header Const.h * @brief 常量表 * @author 编写人 */
|
1 2 3 4 5 6 7 8 9 10 11 12
| /*! * @typedef FruitType * @brief 枚举类型简介 * @constant FruitTypeApple FruitTypeApple简介 * @constant FruitTypeBanana FruitTypeBanana简介 */ typedef NS_ENUM(NSInteger, FruitType){ /// FruitTypeApple简介 FruitTypeApple, /// FruitTypeBanana简介 FruitTypeBanana };
|
自动化工具
VVDocumenter-Xcode,可方便地添加符合规范的注释。
注意事项
1 2 3
| #if DEBUG NSLog(@"something"); #endif
|
工程应采用 ARC,并采用 strong 和 weak 替代传统的 retain, copy, assign。
代码应松紧适度,适当运用空行。避免过度紧凑和过度宽松的代码,如:
过度紧凑的代码:
1 2 3 4 5 6
| task1Step1; task1Step2; task1Step3; task2Step1; task2Step2; task2Step3;
|
1 2 3 4 5 6
| - (void)functionA { } - (void)functionB { }
|
过度宽松的代码:
1 2 3 4 5 6 7 8 9 10 11
| task1Step1; task1Step2; task1Step3; task2Step1; task2Step2; task2Step3;
|
松紧适度的代码:
1 2 3 4 5 6 7 8 9
| // Task1 task1Step1; task1Step2; task1Step3; // Task2 task2Step1; task2Step2; task2Step3;
|
- 应使用多条简单的代码,避免使用单条复杂的代码,以提高代码可读性。如应避免这样的代码:
1 2 3 4
| - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return (section == 0)?55:(section==2?30:20); }
|
应更改为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { if (section == 0) { return 55; } else if (section == 2) { return 30; } else { return 20; } }
|
1 2 3 4 5 6 7 8
| for (int i=0;i<10;i++) { if (i==0) { ... } ... }
|
- 对于参数很多的函数,参数各占一行,并以冒号对齐,如:
1 2 3 4 5 6 7
| - (void)exampleFunctionWithPara:(int)para1 anotherPara:(int)para2 theThirdPara:(int)para3 theFourthPara:(int)para4 { ... }
|
1 2 3 4 5
| [self exampleFunctionWithPara:1 anotherPara:2 theThirdPara:3 theFourthPara:4 theFifthPara:5];
|