在独自编码的工作过程中,并没有专心去认真去考虑代码规范性问题,随着工作时间的推移,更懒得去改变已有的代码习惯~但在新的环境中,在新的团队中却突然发现代码规范的重要性,因为代码不仅是用来实现功能的,代码也是表现一个人的技术能力,技术经验,学习能力,团队协作能力的。
为什么呢?因为代码首先是实现了功能,其次是为了后续的功能性扩展,以及团队同事间的相互维护的。我常常跟同事说,技术可以慢慢掌握,但是习惯却要自始至终的去养成,特别是编码习惯。
接下来就介绍下我的代码规范习惯,其中包括项目文件、代码注释、命名规范、修改规范、常用方法修改规范、UI规范。
为了统一iOS研发的规范标准,使编程工作规范化、标准化、流程化;同时也是为了保证码码的可读性、可维护性。包括以下部分:
a. XCode编辑环境下Objective-C的编码风格和标准。
b. Xcode项目新建的操作规范。
c. 项目的发布规范。
d. 项目所有文件的命名规则。
e. 项目目录结构的标准化(采用MVC,或MVVM)。
适用于iOS研发人员使用Xcode 作为开发工具的iOS开发项目。
必须统一使用能够表现项目实际意义的名字。
例如:XCode中网络图片功能的项目文件被命名为’ SDWebImage.xcodeproj’。
统一命名为’Public.h’或者”Commons.h”。任何文件的命名尽量不要以中文命名。
文件夹目录结构
对于文件的目录要按如下结构创建:
-Classes(项目功能类文件)。
-Commons(常用宏定义类等公共文件)。
-Utils(自定义功能类文件)。
-Externals(常用第三方扩展功用类文件)。
-Resource(视频\声音等资源文件。项目图标\logo\启动页等存放在Assets.xcassets中)。
注意:1、由项目负责人按照规范创建项目。
2、由项目负责人完善开发架构,并添加必要的第三方库(使用PodCocoa安装第三方库)。
2-1、架构:MVC,或MVVM
2-2、视图类型:UINavigationViewController,或UITabbarViewController
2-3、必要第三方库
2-3-1、网络:MKNetworkKit或AFNetwork、Reachability。
2-3-2、数据处理:JTObjectMapping(实体映射)、RegexKitLite(正则限制)、FMDB(数据存储)、LKDBHelper、SSKeychain。
2-3-4、键盘:IQKeyboardManager。
2-3-5、图片:QBImagePickerController(多图选择)、SDWebImage(网络图片)、MJPhotoBrowser(图片浏览)。
2-3-6、UI类:iToast、MBProgressHUD、UIViewExt、MJRefresh、Masonry。
2-3-7、函数式编程:ReactiveCocoa。
2-3-8、异常捕捉:
2-3-9、分享\地图\统计:
3、完善常用的基类
3-1、数据处理基类:BaseModel。
3-2、视图控制器基类:BaseViewController。
每天上班时间从版本库Checkout或Update最新版本的进行开发工作,下班前把开发的工作版本Commit保存到版本库中。
注释是为了对当前定义的类文件,或属性、或变量,或方法进行解释说明,便于后续的阅读及维护。
建议使用VVDocumenter-Xcode注释插件(https://github.com/onevcat/VVDocumenter-Xcode)
注释可以采用’ /**xxx*/ ’,或’ ///xxx ’ ,或’ /*xxx*/ ’,或’ // xxx ’四种注释符号,涉及到多行注释时,尽量使用’ /** xxx */ ’,或’ /*xxx*/ ’。
1)注释尽量采用’ /**xxx*/ ’,或’ ///xxx ’(便于研发人员查看定义说明。当鼠标光标放在代码上面,同时按住键盘上的Alt键时,出现问号,这时点击鼠标时出弹出定义说明)。
2)在.h头文件中添加作者和功能描述说明.
1)注释一般采用’ /** xxx*/ ’,或’ /*xxx*/ ’,或’ // xxx ’,建议多行时采用’ /**xxx*/ ’,或’ /*xxx*/ ’,单行时’ // xxx ’。
2)对于一行代码的注释可放在前一行及本行上,不允许放在下一行,更不允许在一行语句的中间加入注释。
添加、修改、删除时的注释(标注操作起始范围,同时注明类型、操作人、操作时间),如下图所示:
应使用制表符号(Tab),不能使用空格(Space),并且缩进以1个Tab为单位。
每一个中括弧在源码中要单独占一行。
1)关键字与其后的表达式之间要有空格。
如:if (expr),或for (expr)。
2)单目操作符不应该与它们的操作数分开。
如:”!”,或”^”。
3)除”,”外,其它双目操作符应该与它们的操作数用空格隔开。
1).h文件中的空行
文件说明与头文件包含(#import)之间空1行。
头文件包含(#import)之间,如果需要分类区别,各类别之间空1行。
头文件包含(#import)与@class之间空2行。
@interface与@class之间空1行。
头文件{}里面,空1行开始声明对象成员变量,如果需要分类区别,各类别之间空1行。
头文件{}外,空1行开始声明属性,如果需要分类区别,各类别之间空1行。
属性下面空1行开始写方法,如果需要分类区别,各类别之间空1行。
方法声明完成后,与@end之间空1行。
如果需要声明protocol,空2行接着写;通常protocol声明在@interface之前,写在@end后面。
2).m文件中的空行
文件说明与头文件包含(#import)之间空1行。
头文件包含(#import)之间,如果需要分类区别,各类别之间空1行。
@implementation和@synthesize之间空1行,如果需要分类区别,各类型之间空1行。
@synthesize与方法之间空1行。
方法与方法之间空1行。
方法完成后,与@end之间空1行。
功能类方法区分(#pragma mark -)与方法之间空1行。
3)方法里面的空行
变量声明后需要空1行,如果需要分类区别,各类别之间空1行。
条件、循环、选择语句,整个语句结束后需要空1行。
各功能模块之间空1行。
最后一个括弧之前不空行。
注释与代码之间不空行。
#pragma mark – 与方法之间空1行。
4)每行代码最多不超过100个字符。
设置方法:打开Xcode——>菜单栏——>Preferences——>Text Editing——>Page Guideat column(输入100即可)。
1)协议<>前面,及协议方法中有一个空格。
2)变量声明时,类型与变量之间至少1个空格(*号靠近变量,不靠近类型)。
3)属性声明时,@property后留1个空格,()里面,逗号紧跟前一个变量,与后一个变量之间留1个空格。()外面,先留1个空格,再声明属性类型与属性名称,且类型与属性之间留1个空格。(注:先定义原子性-nonatomic,再定义内存管理类型-strong/copy/retain/assign)。
4)方法定义:+/-后面与()之间留1个空格,在多参数方法,每个参数后面都有1个空格,返回类型与*之间留1个空格,方法参数中返回类型与*之间留1个空格。
1)变量、属性定义参照.h文件中的定义规范。同时不能定义在implementation之后。
2)区分功能类
各种类型的文件命名时都采用骆驼命名法,即混合使用大小写字母来构成变量或函数的名字。所有命名都必须要达到见名知其意的效果,然后接其名字,名字为要为所建新类、或图片的功能的描述,其名字的单词均以第一个字母小写开头,其余字母全部为大写。尽量采用有意义的英文单词命名,且避免使用中文拼音,或中文。
如:某个类名:newsDetail.h;图片名:userHead.png;
1)所有的类名,接口名(Protocol),接口名必须是有意义的,后面必须以该类的属性名结尾。
2)继承自UIView的类以View结尾(各UI继承时类似)。
如:usersInfoView、nickNameLabel、headerImageView、loginButton等。
3)继承自ViewController的类以VC结尾。
如:userVC、loginVC等。
4)所有保存数据的实体以Model结尾。
如:userModel等。
5)所有处理数据逻辑的类以ViewModel结尾。
如:userViewModel等。
6)类扩展时,以有意义的英文单词结尾。
如:NSString+regular.h\NSString+regular.m等。
1)方法的名称应全部使用有意义的单词组成,且以小写字母开头,多单词组合时,后面的单词首字母大写,在 -\ + 和返回值之间留1个空格,方法名和第一个参数间不留空格,方法名后必须加注释说明此方法的主要功能。
如:- (void)getUserInformation;
2)设置类变量的内容的方法应使用set作为前缀,读取变量的内容的方法应使用get作为前缀。如用属性则不用关心此问题。
如:
- (void)getUserName;
- (void)setUserName:(NSString*)userName;
3)方法中的参数:第一个参数名称要从函数名称上携带出来,第二个参数的首字母小写,多个单词组合时,后面单词首字母大写。参数有别名时,参数别名与参数名一致,但参数名前缀以_。参数别名与前一参数保留1个空格。参数无别名时,以有意义的字母命名。
如:- (void)myFunctionWithSizeA:(CGSize)sizeA sizeB:(CGSize)_sizeB;
1)变量必须起有意义的名字,使其他研发人员可以很容易读懂变量所代表的意义,变量名称后面必须以该类的类型名结尾(这样就从名称上知道是什么类型,同时避免不同的类型张冠李戴),变量名后还应加注释说明此变量在类中的作用。
如:
NSString *userNameStr;
NSArray *datasArray;
2)对于要和interface builder关联的的输出口变量,命名时要后缀以特定的控件名。
如:IBOutlet UILabel *userNameLabel;
3)尽量避免使用全局变量,如果必须使用全局变量则必须加前缀 ‘ public_’,同时应在变量名称中体现变量的类型。
如:public_userNameStr;
4)私有实例变量前加一个下划线。
如:_userNameStr。
5)枚举变量也要有相应的前缀来区分不同的enum变量。比如苹果公司的一个enum。
如:
typedef enum CGPathDrawingMode CGPathDrawingMode;
/* Drawing modes for text. */
enum CGTextDrawingMode
{
kCGTextFill,
kCGTextStroke,
kCGTextFillStroke,
kCGTextInvisible,
kCGTextFillClip,
kCGTextStrokeClip,
kCGTextFillStrokeClip,
kCGTextClip
};
1)避免在程序中直接出现常数,使用超过两次以上的应以宏定义(未明确类型,或需计算时),或静态变量(已明确类型)的形式来替代。
2)常数的宏定义应与它实际使用时的类型相一致。如以3.0来定义浮点类型,用3表示整型。
3)常量的命名应当能够表达出它的用途,并且用大写字母表示。
如:
static CGFloat const PI = 3.1415926;
#defineCycleArea(r) (PI * (r * r))
4)一些常量前加特殊前缀,可以作为不同常量的区分。
如:
UserDefaultsKey的变量前加UserKey_;
NotificationNameKey前面加NotificationKey_;
DictionaryKey前面加DickKey_;
Objective-c语言的保留字或关键词应全部使用小写字母,除下表中保留字外,private、protected、public、在类型说明中也作为保留字使用。还有nonatomanic、retain、readwrite、
readonly、copy、id、description等也有特殊的使用场合。
这些不管是在iOS研发中,还是在服务端接口返回字段中,全部不用。
_Bool |
_Complex |
_Imaginary |
auto |
break |
bycopy |
byref |
case |
char |
const |
continue |
default |
do |
double |
else |
enum |
extern |
float |
for |
goto |
if |
in |
inline |
inout |
int |
long |
oneway |
out |
register |
restrict |
return |
self |
short |
signed |
sizeof |
static |
struct |
super |
switch |
typedef |
union |
unsigned |
void |
volatile |
while |
视图控制器里包含方法:
1)UI创建方法:- (void)setUI;实现界面的布局,且在- (void)viewDidLoad;里调用。
2)响应方法:如:- (void)buttoClick:(UIButton*)button。
3)代理方法:
4)网络请求方法:- (void)loadData;
5)setter方法:如:- (UILabel *)nameLable{……}
常用公共方法,建议封装成类进行使用(封装时,可以采用先扩展后继承,或直接继承的方式进行),便于统一管理、维护。
1)视图控制器属性设置方法。
如:导航栏样式、导航栏标题、导航栏返回按钮、导航栏右按钮、导航栏背景等。
2)网络请求与实体映射方法。
如:数据实体映射、网络请求、网络数据缓存等。
3)通知处理类方法。
如:发送通知、接收通知、移除通知等。
4)数据缓存方法。
如:NSUserDefault(转量级)、plist文件、FMDB、CoreData等。
注:iPhone5全屏的尺寸为640 X 1136,其他控件尺寸与iphone4一样。(以上及下文描述图片尺寸均为第一套小图尺寸,高清图片尺寸要求详见4.2.6)
导航条背景图:navigationBackground.png
导航条左按钮:navigationRightBtn.png
导航条右按钮:navigationLeftBtn.png
导航条返回按钮:navigationBackBtn.png
Tab 栏目背景图:tabBackground.png
Tab 栏目项目:tabItem_News.png、tabItem_xxx.png
Tab 栏目项目选中高光:tabItemHightlight_News.png、tabItemHightlight__xxx.png
Tab 栏目项目选中背景:tabItemSelected_News.png、tabItemSelected_xxx.png
界面普通按钮必需按照实际使用有意义的动作而命名。命名规则根据总原则以实际动作定义(必须使用英文标示),并_Btn,或button结尾以标识是一个按钮。
比如登陆按钮:login_Btn.png,或loginButton.png
Logo尺寸:1024 x 1024
圆角效果。图标的圆角效果是系统自动加上的,我们不能控制。这也是为什么我们看到的每个图标,其圆角效果是完全相同的。
光晕效果。光晕效果也是系统加上的,和“圆角”不同的是,光晕效果是一个可选项。我们可以通过设置app的光晕参数(UIPrerenderedIcon),告诉系统是否要为我们的图标打上光晕效果。
开机画面,即启动页面,根据适配不同机型需要多套图片。
iOS 7-9(iPhone Portrait ) 2x = 640 x 960
iOS 7-9(iPhone Portrait ) Retina 4 = 640 x 1136
iOS 8-9(iPhone Portrait)Retina HD 4.7 = 750 x1334
iOS 8-9 (iPhonePortrait) Retina HD 5.5 = 1242 x2208
iOS 8-9(iPhone Landscape) Retina HD 5.5 = 2208 x 1242
iOS 5-6(iPhone Portrait ) 1x = 320 x 480
iOS 5-6(iPhone Portrait ) Retina 4 = 640 x 1136
iOS 5-6 (iPhone Portrait)2x = 640 x 960
iOS使用的图片格式统一为png,并且严格按照特定UI控件大小制作图片。
特定UI控件有:开机界面,界面背景,导航栏(NavigationBar),状态栏(Tabbar),状态栏按钮,icon(Logo)。
iOS每张图片必须要有2套size,如果是全屏类型的图片则需要多套size。
第一套图片以@2x.png结尾,在iPhone5S(640 x 1136)环境下切图;
第二套图片以@3x.png结尾,在iPhone6S(1242 x 2208)环境下切图。
对研发规范达成统一认识。
对研发管理达成统一认识。
对研发产品达成统一认识。
研发人员的自我控制,主要体现在研发过程中的对代码质量的把控。即测试,首先是对多系统版本(iOS5.0……iOS9.2等)测试;其次是对多尺寸版本(iPhone4.0……iPhone5.5等;iPad各尺寸)测试;最后多类型网络(WiFi、手机2G、3G等)测试。
具体还包括以下几个这方面:
1、UI
1-1、跨系统版本下的UI是否符合UI设计
1-2、背景颜色、字体大小、字体颜色、UI间距等是否符合UI设计
1-3、图片的使用
1-4、信息异常(空字符、空值、字符超长)时的显示
2、用户交互体验
2-1、操作习惯
2-2、点击、滑动等手势
3、网络情况
3-1、无网络
3-2、有网络
3-2-1、有网络无数据
3-2-2、有网络有数据,数据异常(格式、类型)
3-2-3、有网络网络异常(延迟、时断时续不稳定)
4、输入情况
4-1、数组越界或字符子串越界(越界闪退)
4-2、空值设置(数组或字典对象赋nil值)
4-3、键盘处理情况
4-3-1、编辑过程中,自适应键盘高度,避免被键盘遮挡
4-3-2、编辑结束后,键盘隐藏(按钮事件,手势事件)
4-4、键盘类型(数字、字母等类型)
4-5、单行、多行情况
5、功能中断
5-1、版本不支持
5-2、硬件不支持
5-3、接听电话、或收发信息时的情况
6、信息安全
6-1、帐号测试
6-2、用户信息安全性
6-3、数据操作(存储操作)
1、配置
适配设备(仅支持iPhone设备;仅支持iPad设备;同时支持iPhone、iPad设备);
适配系统版本(5.0……9.2任选其一);
转屏适配(是否支持多方向屏幕适配,如横屏、竖屏等);
版本标识符(Bundle Identifier);
版本号(Version);
版本创建(Build);
APP名称(Bundle display name);
2、架构
MVVM(model;view;controller;viewModel);
架构目录(Classes;Commons;Externals;Utils;Resource);
视图模式(UITabbarController+UINavigationController、SliderView+UINavigationController等);
第三方库(采用podCocoa导入;如:FMDB、SSKeychain、LKDBHelper、MKNetworkKit、Reachability、JTObjectMapping、MBProgressHUD、MJRefresh、IQKeyboardManager、Masonry、ReactiveCocoa、RegexKitLite、SDWebImage等);
基类(视图控制器基类;数据模型基类等);
常用功能类(时间处理、字符处理、UI初始化、倒计时等);
扩展功能处理(异常捕捉、在线更新bug);
3、版本管理
SVN版本库(更新提交commit、更新下载update);
4、开发资料
注册开发者帐号。
1、研发前
熟悉代码规范文档。
熟悉测试用例。
了解产品需求。
制定研发制度(会议管理制度、代码走查制度)。
2、研发中
按照代码规范进行编码,保证项目代码风格一致性。
按照测试用例进行编码,保证项目少出bug,尽量不出bug。
按照产品需求进行研发。
根据需要添加第三方库(如高德地图、友盟统计、分享shareSDK等)。
注意事项:
尽量采用纯代码,少用xib/stroreBoard。
注意多尺寸版本的布局适配。
注意多系统版本的适配。
注意各种crash情况的处理。
3、研发后
进行单元测试验证(或交叉测试验证),保证代码质量。
进行集成测试验证,保证功能稳定性。
1、资料准备
公司介绍资料(包括公司网站、用户协议等网站)。
产品资料(介绍信息、logo、介绍图片、启动页等)。
2、发布审核
发布成功后,关注是否审核通过。