iOS代码规范
2018-10-24 本文已影响285人
yanhooIT
-------------------------------------编码原则-------------------------------------
- 需求是暂时的,只有变化才是永恒的,
面向变化编程
,而不是面向需求编程; - 不要过分追求技巧,从而降低
程序的可读性
; - 简洁的代码可以让bug无处藏身,要
写出明显没有bug的代码
,而不是没有明显bug的代码
; - 先解决问题,再考虑将来的扩展问题。
-------------------------------------编码原则-------------------------------------
名词定义
-
大驼峰
式命名:每个单词的首字母
都采用大写
字母 -
小驼峰
式命名:第一个单词
首字母小写
,剩下单词的首字母大写
命名规范
- 命名原则
- 明确表达含义,尽量做到不需要注释也能了解其作用,
若做不到,就加注释
; - 使用全称,尽量不使用缩写(
使用规范的缩写,不要自创
); - 公共接口不仅命名要规范,也要添加上注释,方便使用者快速了解接口的含义,最好在注释里给上使用示例;
- 明确表达含义,尽量做到不需要注释也能了解其作用,
类名
- 采取
大驼峰
式命名 - 示例:XXHomeViewController,
XX是项目前缀
,不属于命名范畴,这里不要产生误解
私有变量
- 私有成员变量在.m文件中声明
-
以_开头
,小驼峰式命名,示例:NSString *_privateVar;
property变量
-
小驼峰
式命名,示例:@property (nonatomic, copy) NSString *propertyName
; - 属性的修饰关键字推荐排序:
原子性,读写权限(默认是可读写),内存管理
,示例:
@property (nonatomic, readonly, copy) NSString *propertyName;
-
NSString、NSArray、block属性
应该使用copy
关键字;
宏常量命名
-
#define
预处理定义的宏常量全部大写,单词间用_
分隔,示例:#defineSCREEN_BOUNDS
[[UIScreen mainScreen] bounds] - 宏定义中如果包含表达式或变量,表达式或变量必须用
小括号括起来
,示例:
#define SCALING ([[UIScreen mainScreen] bounds].size.width/375.f) // 缩放比例
类型常量命名
- 对于局限于.m文件中的的常量,
以字符k开头
,示例:static const NSTimeInterval kAnimationDuration = 0.3; - 对于定义于
.h文件
中的常量,对外部可见,则以定义该常量所在类的类名开头
(仿照苹果风格),在头文件中使用UIKIT_EXTERN
声明,在.m文件
中定义其值,示例:
//在.h文件中:
UIKIT_EXTERN NSString * const UIApplicationStatusBarOrientationUserInfoKey;
//在.m文件中:
NSString * const UIApplicationStatusBarOrientationUserInfoKey = @"xxxxxx";
枚举
- 与类的命名规则一致,采取
大驼峰
式命名,示例:UIControlState - 枚举内容的命名需要以该枚举的类型名称开头,示例:
UIControlState
Normal -
NS_ENUM
定义通用枚举,NS_OPTIONS
定义位移枚举,详见位移枚举NS_OPTIONS详解
delegate
- 用
Delegate
做后缀,示例:UIScrollViewDelegate
- 用
@optional
修饰可选实现
的方法,用@required(默认值)
修饰必须实现
的方法 - 类的实例
必须
为代理方法的参数之一- 如果只有
一个
参数,方法名要符合实际含义,示例:- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
- 如果有
两个及以上
参数,以类的名字开头,以表明此方法是属于哪个类的,示例:- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
- 如果只有
- 当你的
代理的方法过多
, 可以拆分数据部分和逻辑部分
, 数据部分用DataSource
做后缀,示例:UITableViewDataSource
- 使用
did
和will
通知Delegate
已发生的变化 或 将要发生的变化
方法
- 方法名用小驼峰式命名
- 方法名不要使用
new
作为前缀 - 不要使用
and
来连接属性参数,如果方法描述两种独立的行为,使用and
来串接它们 - 方法实现时,如果参数过长,则令每个参数占用一行,以冒号对齐
- 方法名要与对应的参数名保持高度一致
- 示例汇总
方法命名规范
代码注释
注释规范
- 优秀的代码大部分是可以自描述的,完全可以用代码本身来表达它到底在干什么,而不需要注释的辅助。
- 即使代码有自描述,也建议在以下三种情况写好注释:
- 公共接口(注释是用来快速告诉阅读代码的人,当前类实现什么功能);
- 涉及到专业知识的代码(注释要说明实现原理和思想);
- 容易产生歧义的代码(严格来说,容易让人产生歧义的代码是不允许存在的);
- 备注:除了上述三种情况,如果别人还是只能依靠注释才能读懂你的代码,就要反思你写的代码了。
- 对于注释的内容,相对于
做了什么
,更应该说明为什么这么做。
import注释
- 如果有一个以上的
import
语句,就要对这些语句进行分组,示例如下图:
import注释
属性注释
- Xcode8已经集成了喵神的插件VVDocumenter,使用快捷键
command+option+/
即可自动生成注释模板,直接看示例:
属性注释
方法声明的注释
- Xcode8已经集成了喵神的插件VVDocumenter,使用快捷键
command+option+/
即可自动生成注释模板,直接看示例:
方法声明的注释
代码块注释
- 单行的用
//+空格
开头 - 多行的采用
/** */
注释
TODO
- 使用
//TODO:
来标记一些未完成
的地方,这里的 TODO 和 // 之间的空格就不需要
了
代码格式
指针 * 的位置
- 靠近变量,示例:NSString *_userName;
方法的声明(定义)
- 在 - 、+ 和 返回值 之间留一个空格,方法名和返回值之间不留空格,方法名和参数之间不留空格,示例:- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index;
代码缩进
- 在 Xcode > Preferences > Text Editing 将 Tab 和自动缩进都设置为4个空格
- 多个方法的声明(定义),Method1 与 Method2 之间空一行
- 一元运算符与变量之间没有空格,示例:!varName;
- 二元运算符与变量之间必须有空格,示例:(逻辑运算) ? 选项1 : 选项2;
不要出现一行多句代码
controller中的方法分组
controller中的方法分组view中的方法分组
view中的方法分组大括号写法规范
-
首先看一下苹果默认生成的代码中大括号的写法
大括号的写法 - 对于其他使用场景
(if、for、while、switch等)
,左括号跟在第一行后边,留一个空格,以下都是系统默认生成的,注意大括号的位置
if、for、while、switch等 -
对于switch语句中的各个case中的业务逻辑使用大括号阔起来
case中的业务逻辑使用大括号阔起来
编码规范
if语句
-
不要使用过多的分支,要善于使用return来提前返回错误的情况,把最正确的情况放到最后返回,示例:
image.png -
条件过多,过长的时候应该换行
image.png -
条件语句的判断建议:变量在右,常量在左
image.png
for语句
- 尽量使用for in循环语句
switch语句
-
每个分支都必须用大括号括起来
image.png - 使用枚举类型时,不能有default分支,因为在s
witch
语句使用枚举类型的时候,如果使用了default
分支,新增枚举类型时就无法通过编译器来检查到新增的类型 - 除了使用枚举类型以外,都必须有default分支
函数
- 一个函数只做一件事(单一原则)
- 对于有返回值的函数(方法),每一个分支都必须有返回值
- 对输入参数的正确性和有效性进行检查,参数错误立即返回
- 如果在不同的函数内部有相同的功能,应该把相同的功能抽取出来单独作为另一个函数
- 将函数内部比较复杂的逻辑提取出来作为单独的函数