iOS 项目组简则

版本 更新记录

1.0.1
  1. 修正一些规范类错误;
  2. Git 提交类细化补充部分条款;
  3. 代码规范类及命名规范补充。

1.0.0
  1. 整理 Git 提交简则;
  2. 错误类检查简则;
  3. 代码规范类检查简则(建议类)。

一、Git提交简则

每天下班前保存代码至 Git 服务器

每天下班前将当天 coding 的代码提交至 Git 服务器。

不修改他人未上线的代码

开发时只修改与自己相关的代码,他人正在开发的代码,任何修改都需要与对应开发商量。

主分支不要直接提交代码

代码修改,问题修复在分支进行,不要直接提交至主分支,方便回滚代码。

分支建立删除专人负责

分支的建立和删除清理由专人负责,不要自己操作。

不提交无用的代码

每次提交都要逐行检查要推送到 Git 服务器的代码,如果是没必要的修改,即使一行空格,一个逗号,也不要上传,影响文件的修改历史及代码检查。

公共类或组件修改通知组长

公共类修改与组长商量,评估修改方案的影响,以及可能多人共同修改造成的冲突。

推送至 Git 服务器代码要有说明

  • 每次提交都要文字说明相应动作,例如相应的增删改修,新增加XX需求功能界面,删除XX多余的文件/方法,修改XX接口的名称,修复什么文件什么问题等等;

  • 若条目过多,可在相应条目下逐条列出。

提交/合并前移除调试代码测试数据等

  • 自己调试测试的代码,如 NSLog,在提交至 Git 或合并前请移除,会干扰其他人 Debug;

  • 测试数据要记得移除,例如测试报文,plist 配置文件中的测试配置等等。

二、错误类检查

新增代码 ARC 标记

若项目为 MRC,但写的代码都是按照 ARC 格式写的,按照 ARC 写的代码必须加上 -fobjc-arc 标记;同理如果 ARC 的项目,部分第三方库为MRC,则需在三方库的类增加 -fno-objc-arc 标记。

检查属性修饰符

  • 属性修饰 strong,weak,copy,assign 分清楚,ARC 不要用 retain,release;
  • 普通对象一般用 strong 修饰;
  • 代理用 weak 修饰;
  • 字符串一般用 copy 修饰;
  • Block一般用 copy 修饰;
  • 基本数据类型用 assign 修饰。

通知注意移除

  • 通知只在必要时使用,且记得移除;
  • 如在 - (void)dealloc 方法中或通过其他方式移除。

内存泄露检查

  • 逻辑分析是否会造成循环引用,若会循环引用,则用 __weak 和 __strong 解决;
  • 代码自检时可通过重写 - (void)dealloc 方法,查看此方法是否执行;
  • 可以通过 command+shift+B 快捷键进行静态分析,或者通过 Instrument 查看是否存在内存泄露。

检查循环引用

  • NSTimer,Delegate, Notification,KVO, Block 在引用对象销毁时及时移除;
  • 是否会造成循环引用,导致引用对象无法释放。

主线程刷新 UI

检查刷新 UI 是否在主线程操作。

线程安全检查

是否有多线程操作同一变量/文件,若有记得加锁。

static 关键字检查

不要在其他类中修改用 static 修饰的全局变量。

变量要初始化

  • 声名的变量要记得初始化;
  • 方法内声名的局部变量,必须赋予初始值,例如声名的 BOOL 变量,不初始化会出现随机值。

编译器警告处理

编译器给出的警告,例如循环引用,api 过期,方法未调用(无用的方法),都需要仔细检查,尽量处理掉。

id 类型变量检查

不滥用 id 类型,变量声明尽量确定类型,确保编译器正确的推断结果类型。

不随意引入三方类

第三方类引入前与组长商量,确保引入库的安全性,健壮性及可维护性。

不私自引入三方接口

不可私自引入第三方接口,如网络上面的查询 IP 接口,一旦第三方接口关闭或者起诉 App 占用流量,后果严重。

理解拷贝的代码段

  • 从网络上找到代码段,解决方案等,自己必须先完全读懂理解,无法理解可与组长商量;
  • 例如网络上 C/C++ 的方法可能存在内存泄露,正则表达式包含条件过多,api 接口可能为私有 api等等。

Cell 复用问题检查

  • Cell 从缓存池中取出,应该重新赋值;
  • 如果有条件判断,是否考虑了所有情况,例如有 if 是否有 else 处理;
  • NSTimer, Notification,KVO 是否重复添加监听,滚动后重复执行方法。

界面适配类检查

  • 界面适配所有要求的机型,4英寸、4.7英寸、5.5英寸、5.8英寸等都需要适配测试;
  • 键盘遮挡输入框检查,悬浮窗不能影响功能正常使用。

常识类错误检查

  • 思考提示文字/标题,效果图文字可能是错误的,注意容易产生歧义的文字,如登录/登陆,终点/中点等等;
  • 输入校验,与安卓核对,与业务确认,交易密码/卡号/金额/邮箱等等,例如邮箱不能输入中文。

数组字典类检查

  • 判断数组是否可能越界,若有可能越界,先对索引进行判断;
  • 数组/字典取出的值为 nil 是否引起崩溃,空值对逻辑影响;
  • 可变数组赋值给不可变数组要加 copy。

KVC 检查

  • 字典转模型时,处理forUndefinedKey:情况,防止后台字段增减引起崩溃;
  • 用 {} 快速创建字典时判空 nil 处理,否则引起 Crash。

三、代码规范类检查

少用全局变量

  • Appdelegate 中不准增加全局变量(特殊情况除外),如需全部变量,可定义在单例中;
  • 单例或 Appdelegate 中的全局变量,对象文件中的属性,必须注明用途及默认值;
  • 方法间传值可用参数注入的方式,不要创建过多属性;
  • 如果对象之间通讯可用属性/Block/Delegate 传值,就不要用单例的全局变量传值。

业务模块减少耦合

不同业务模块之间尽量减少耦合,如一些简单的转换的方法,用到的地方不多,可直接在业务功能模块中实现,不必写到公共模块中,减少类似 common 的公共类,业务模块之间减少耦合。

方法内聚性

  • 方法要具有内聚性,在方法内部尽量不要引用全局变量/属性,方法功能尽量单一,可以在内部处理完成后,通过返回值的形式返回处理结果;
  • 传值可通过参数注入的方式,即传参的形式传值。

方法简短单一

单个方法长度尽量不要超过一屏幕,超过一屏幕可以考虑拆分。

代码分段注释

  • 不同功能代码段可分段注释,保持代码组织性,是代码更清晰;
  • 例如 lifecycle/DataSource/delegate/lazy loaded 等等;
  • 可用 #pragma mark - 代码段说明;
  • 可用 ///MARK: - 代码段说明。

代码注释

  • 变量属性注释,全局的变量必须要注释其作用;
  • 方法注释,没有参数、返回值的方法使用单行注释,否则使用多行注释,方法要注明作用及参数含义及返回值含义;
  • 类注释,每个新建类 .h 文件头部说明此类功能。

宏定义或 Const 常量

  • 定义宏或 Const 常量,对于重复的常量可使用宏,定义加k前缀,并在行尾注释其作用;
  • 例如 #define kPhoneCellHeight 44 //手机卡片列表Cell高度
  • 宏定义的位置,个别对象内部需要用到的变量,不需要定义公共头文件或 PCH 文件中。

四、命名规范

注意:命名一律用英文,不要用拼音或汉字。

切图文件命名规范(模块_类别_功能_状态)

每一部分用下划线分隔,图片名中两倍图在名字最后要加@2x,三倍图在名字最后要加@3x。

示例(导航栏通知按钮 normal 状态切图):

模块\_类别\_功能\_状态

nav\_btn\_noti\_normal@2x.png

类命名规范(前缀 - 模块 - 类别

  • 每个模块都应该有一个前缀,例如相册模块(photo album)前缀可为 PA ,我的模块(Mine)前缀可为 MN ,遇见模块前缀冲突可加成前缀名称,一般不超过 4 个字母;
  • 参考前缀 - 模块 - 类别模板,例如我的 - 设置功能,可命名 MNSettingView
  • 类名(以及类别、协议名)应首字母大写,并以驼峰格式分割单词。

方法命名

方法命名采用帕斯卡(pascal)命名法,与驼峰命名法的区别是首字母小写,其他单词首字母大写,每个空格分割的名称单词小写。执行性的方法应该以动词开头,小写字母开头,返回性的方法应该以返回

例如参考 UIResponder 类的一个方法:

- (BOOL)canPerformAction:(SEL)action withSender:(nullable id)sender;

属性、变量命名(功能 - 类别

方法命名采用帕斯卡(pascal)命名法,例如提交按钮,可命名为 submitBtn

@interface ViewController ()

@property (nonatomic, strong) UIButton *submitBtn;

@end

类成员变量名(功能 - 类别

类成员变量命名采用帕斯卡(pascal)命名法,且前面需要加下划线,例如提交按钮可命名为 UIButton *_submitBtn;

@interface ViewController ()
{
BOOL isFirstIntoVC;
UIButton *_submitBtn;
}

@end

对外接口规范

所有对外接口(包括方法和属性),都放在.h文件进行声明,私有的属性放到 extension 里面,私有方法尽量不要放在控制器中,减少控制器的代码量。

//.h文件
@interface CdbObject : NSObject
// 提供外部调用的方法和属性
@end
// ==================分割线====================
//.m文件
@interface CdbObject ()
// extension里面写私有的成员变量
@end
@implementation CdbObject
// 方法实现
@end

对象属性初始化尽量在懒加载中初始化,规范统一;且对象的Getter放在最底部。

///MARK: - Lazy Load
// 搜索按钮
-(UIButton *)searchBtn{
if (_searchBtn == nil) {
UIButton *tempBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[tempBtn setTitleColor:[UIColor purpleColor] forState:UIControlStateNormal];
[tempBtn setTitle:@"搜索" forState:UIControlStateNormal];
tempBtn.titleLabel.font = [UIFont systemFontOfSize:13];
[tempBtn sizeToFit];
_searchBtn = tempBtn;
}
return _searchBtn;
}

五、参考链接

https://www.jianshu.com/p/24a9abcfdba9

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦