一、学习笔记
-
工程中编程的基本原则:
- 应该保持代码的简洁清晰,不要过分追求技巧而降低了程序的可读性
- 编程时需要同时考虑代码的可测试性
- 实现时首先考虑功能的正确性,其次再考虑效率、质量等问题,但是不能不考虑效率和质量问题
- 合理地规划函数的功能粒度,既要避免将所有功能都放在一个函数中实现,导致该函数过于臃肿,也要避免函数功能过于简单,导致函数数量过多
- 在编程时鼓励多用注释,但是在最后交付时要删掉多余的或重复的注释,要求在修改代码时一定要修改对应的注释(一般要求源程序中有效注释量占30%左右)
-
iOS 代码规范:
-
命名规范:长的、描述性的命名是好的
- 类名:
- 使用大驼峰命名法
- 使用继承的类型结尾:比如
XxxViewController
、XxxView
、XxxCell
、XxxDelegate
、XxxDatasource
等
- 属性/变量名:
- 使用小驼峰命名法
- 除非是一些极其常用的缩写,比如
VIP
,其他的都不能缩写,尽量达到只看名字就可以知道这个变量的作用的效果 - 以类型作为后缀,如
xxButton
- 私有变量推荐以下划线
_
开头,如NSString *_privateVariable
- 局部变量和全局变量不能重名(虽然不会报错),可以使用一致的前缀来区分全局变量和局部变量
- 尽量避免变量名中出现数字编号,如
value1
、value2
等,除非逻辑上确实需要编号
- 方法名:使用小驼峰命名法;
- 图片资源名:格式为
功能模块名_类型_功能_状态@nx.类型
,不能有中文、大写字母、特殊符号和空白,如Setting_Button_search_selected@2x.png
- 类名:
-
变量:
- 一个变量最好只有一个作用,不能为了方便,将一个变量用于多个功能,比如某个变量在某部分代码后就没用了,所以自己为了方便就继续在后面的代码中实现其他功能时继续使用这个变量,这样虽然在写的时候自己不会混淆,但是过一段时间再来看,或者其他人阅读代码时就很容易混淆,并且可能会出现意想不到的错误
- 方法内部局部变量推荐在靠近使用的地方声明,不推荐在方法一开始声明所有的局部变量(如果代码比较少则无所谓)
-
条件表达式:
-
当条件过多、过长时,为了避免某一行代码过长,应该使用换行
if (condition1() && condition2() && condition3() && condition4()) { // ... }
-
不能在条件判断语句和循环语句中进行计算或赋值(在学习C语言时可能都做过这样的题,理论上是不会报错的,但是在工程中这样写是非常不好的)
if ((fWidth = 50 * fLength) < 100) { ... }
-
在条件判断语句中,如果是用整型变量与0比较时,不可以模仿布尔值的判断方法,而应该用
==
或!=
和0直接比较// 推荐 if (num == 0) {} // 不推荐 if (!num) {}
-
条件判断是应该是变量在左条件在右
// 推荐 if (i == 0) { ... } // 不推荐 if (0 == i) { ... }
-
switch
语句中每个case
都需要用{}
括起来 -
switch
语句必须要有default
分支,除非是对枚举变量进行switch
-
-
布尔值:在
OC
中使用YES
和NO
,nil
也会被解析为NO
,在条件语句中不要用变量与YES
、NO
和nil
比较// 推荐 if (someObject) {} if (![anotherObject boolValue]) {} // 不推荐 if (someObject == nil) {} if ([anotherObject boolValue] == NO) {} if (isAwesome == YES) {} if (isAwesome == true) {}
-
对于
init
方法和类的构造函数,返回类型应该是instancetype
而不是id
,这样确保编译器正确地推断结果类型 -
代码组织:在函数分组中使用
#pragma mark -
来分类,上空两行,下空一行,常见的结构如下#pragma mark - Lifecycle - (void)viewWillAppear:(BOOL)animated {} - (void)viewDidAppear:(BOOL)animated {} - (void)viewDidLoad {} - (void)viewWillDisappear:(BOOL)animated {} - (void)viewDidDisappear:(BOOL)animated {} - (void)dealloc {} #pragma mark - Custom Accessors - (void)setCustomProperty:(id)value {} - (id)customProperty {} #pragma mark - IBActions - (IBAction)submitData:(id)sender {} #pragma mark - Public - (void)publicMethod {} #pragma mark - Private - (void)privateMethod {} #pragma mark - UITableViewDataSource - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {} #pragma mark - UITableViewDelegate - (nullable NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {} #pragma mark - Getter/Setter // ...
-
函数实现、
if
、switch
、for
、while
等后面的{
都不需要另起一行- (void)setup { if (true) { // ... } }
-
在类的
.h
文件中尽量少引用其他头文件,比如在类A
中需要声明一个类B
的实例变量,这时候不应该引入类B
的头文件,而应该使用向前声明,这样就不会在类A
的.h
文件中引入类B
的全部内容,减少了编译时间// A.h #import <Foundation/Foundation.h> @class B; // 向前声明 @interface A : NSObject // 在A的.h文件中需要定义B的实例对象,但在.h文件中不需要知道B的具体内容 @property (nonatomicm, strong) B *b; @end // A.m #import "B.h"
-
如果方法参数过多过长,应该多行书写,每个参数一行,根据冒号对齐,声明、定义、调用的时候都是这样
- (void)doHomework:(NSString*)name period:(NSInteger)second score:(NSInteger)score;
-
如果函数名的第一部分很短则根据第一部分的首字母进行对齐或者统一缩进4个字符,因为这样冒号的位置就很靠左,后面的部分可能写不下,比如
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask {}
-
注释符和注释内容之间要有一个空格
-
长表达式(超过80列)要在低优先级操作符处换行,操作符放在新行行首,以突出操作符,新行进行适当的缩进,与上一行对齐
if (A == 1 && B == 1 ... || C == 1 && D == 1 ...)
-
在类声明中包含多个
protocal
时,推荐每个protocal
占一行,缩进两个字符或者与第一个protocal
对齐@interface DemoViewController() <UITabBarControllerDelegate, UITabBarControllerDatasource, UITextFieldDelegate, UITextFieldDatasource>
-
函数的规模不能太大,尽量控制在200行之内
-
避免过多直接使用立即数,可以使用宏定义
-
二、参考链接
- iOS 代码规范