命名规范
iOS开发者规范:以苹果开发者中心规范为标准(Coding Guidelines for Cocoa),以此为标准添加部分规范.
iOS命名两大原则是:可读性高和防止命名冲突(通过加前缀来保证). Objective-C 的命名通常都比较长, 名称遵循驼峰式命名法. 一个好的命名标准很简单, 就是做到在开发者一看到名字时, 就能够懂得它的含义和使用方法. 另外, 每个模块都要加上自己的前缀, 前缀在编程接口中非常重要, 可以区分软件的功能范畴并防止不同文件或者类之间命名发生冲突, 比如相册模块(PhotoGallery)的代码都以PG作为前缀: PGAlbumViewController, PGDataManager.
命名
命名规则对于维护代码来说是非常重要的,。Objective-C方法名往往很长,不过这也有好处,方法即注释。
命名规则采用驼峰法:除第一个单词之外,其他单词首字母大写。
基本原则
1. 清晰
又清晰又简洁是最好的了,但简洁不如清晰重要。总的讲不要使用单词的简写,除了非常常用的简写以外,尽量使用单词全称。
API的名称不要有歧义,一看你的API就知道是以什么方式做了什么事情,不要让人有疑问
2. 一致性
做某个事情代码通常都叫这个名字,比如tag、setStringValue,那么你也这么叫。
你在不确定怎么起名字的时候,可以参考一些常用的名字:Method Arguments
类命名
类名(不包括类别和协议名)应该用大写开头的大驼峰命名法。类名中应该包含一个或多个名词来说明这个类(或者类的对象)是做什么的。
在应用级别的代码里,尽量不要使用带前缀的类名。每个类都有相同的前缀不能提高可读性。
不过如果是编写多个应用间的共享代码,前缀就是可接受并推荐的做法了(型如 JKPhotoBrowser ).如
@interface ImageBrowseView :UIView
@end
@interface JKPhotoBrowser :UIView
@end
类别命名
类名+标识+扩展(UIImageView +HP+Web)
例:如果我们想要创建一个基于UIImageView 的类别用于网络请求图片,我们应该把类别放到名字是UIImageView+HPWeb.h的文件里。UIImageView为要扩展的类名,HP为专属标识,Web为扩展的功能。
类别的方法应该都使用一个前缀(型如hp_myCategoryMethodOnAString ),以防止Objective-
C代码在单名空间里冲突。如果代码本来就不考虑共享或在不同的地址空间(address-space),方法命名规则就没必要恪守了。
类别HPWeb头文件,UIImageView+HPWeb.h如下:
@interface UIImageView (HPWeb)
(void)hp_setImageWithURLString:(NSString *)urlStr;
@end
协议(委托/代理)命名
与类命名相同,此外需添加“Delegate”后缀
举例:ReplyViewDelegate
方法命名
1.首字母小写,之后每个单词首字母都大写
2.方法名使用动词短语
举例:- (void)setPostValue:(int)value
方法参数命名
1.首字母小写,之后每个单词首字母都大写
2.具有足够的说明性
3.不需要添加类型前缀
举例:- (void)sendUserInfo:(NSDictionary *)userInfo
方法命名
方法使用小驼峰法命名, 一个规范的方法读起来应该像一句完整的话,读过之后便知函数的作用。执行性的方法应该以动词开头,小写字母开头,返回性的方法应该以返回的内容开头,但之前不要加get。
如:
- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;
(instancetype)arrayWithArray:(NSArray *)array;
如果有参数,函数名应该作为第一个参数的提示信息,若有多个参数,在参数前也应该有提示信息(一般不必加and)
一些经典的操作应该使用约定的动词,如initWith,insert,remove,replace,add等等。
变量命名
变量名使用小驼峰法, 使变量名尽量可以推测其用途属性具有描述性。别一心想着少打几个字母,让你的代码可以迅速被理解更加重要。
1. 类成员变量:
类中所有成员变量以属性的方式提供,不要使用其他类型的变量声明
示例:
@interface ViewController ()
@property (nonatomic,strong)NSMutableArray *dataArray;
@property (nonatomic,strong)UITableView *tableView;
@end
@implementation ViewController
@end
2. 一般变量命名
示例:
NSMutableArray *ticketsArray = [NSMutableArrayarrayWithCapacity:0];
NSInteger numCompletedConnections =3;
3. 常量命名
常量(预定义,枚举,局部常量等)使用小写k开头的驼峰法,比如kInvalidHandle ,kWritePerm
示例:
#define kRunAnnotationStartPointTitle @"起点"
枚举请使用oc风格,不要使用C语言风格
typedef NS_ENUM (NSInteger,RunGoalTypeE){
kRunGoalTypeNone = 0, //无目标
kRunGoalTypeTime = 1, //以时间为目标
kRunGoalTypeDistance = 2, //以距离为目标
kRunGoalTypeCalori = 3, //以消耗卡路里为目标
};
字符串常量使用const修饰
NSString *const kGroupInfoName =@"name";
图片资源文件命名
如果设计人员提供的图片不复合规范,请开发人员让相关人员进行修改再使用。UI设计规范。
先看下新浪微博app图片资源命名方式,下面是部分截图
以下为相关要求:
图片资源命名方式,以功能为组织形式,是一个很好的习惯,有利于查看资源文件。
原则:
- 采用单词全拼,或者大家公认无岐义的缩写(比如:nav,bg,btn等)
- 采用“模块+功能”命名法,模块分为公共模块、私有模块。公共模块主要包括统一的背景,导航条,标签,公共的按钮背景,公共的默认图等等;私有模块主要根据app的业务
- 功能模块划分,比如用户中心,消息中心等
备注:建议背景图采用以bg作前缀,按钮背景采用btn作前缀(不作强制要求,项目实际负责人根据团队特点确定即可)
公共模块命名示例:
导航条背影图片:bg_nav_bar@2x.png
导航返回按钮:bg_nav_back_normal@2x.png,
bg_nav_back_selected@2x.png
标签item背景:bg_tabbar_record_normal@2x.png,bg_tabbar_record_selected@2x.png
私有模块命名示例:
以Joggers APP的用户中心图片资源为例说明,
uc——user center+
用户中心头像默认图:bg_uc_avatar@2x.png
用户中心顶部默认背景图:bg_uc_top_defaut@2x.png
用户中心底部背景图:bg_uc_bottom@2x.png
这部分工作较为繁杂,并且在程序员心中会认为是技术含量较低的一个工作,但图片命名的严谨性同样会反映出我们对细节的追求,细节决定成败。
补充规范
1. 删除多余的空行
所有方法与方法之间空1行
所有代码块之间空1行
2. 删除多余的注释
删除注释掉的代码
删除没有意义的注释
3. 删除多余的方法
如果方法没有使用到,请删除它
如果方法没有执行任何业务逻辑,请删除它或者给出一定注释
4. 删除未被使用的资源文件
5. 添加必要的注释
所有 .h 文件中的property 需要给出注释
所有自定义的方法需要给出注释
比较大的代码块需要给出注释
所有代码中出现的阿拉伯数字需要给出注释
程序中出现加密/解密 逻辑的操作地方,需要给出注释说明过程(无论是系统还是自定义)
6. 整体代码风格需要统一
代码后面的”{“ 不需要单独占用一行
逻辑运算符 与 代码之前空一格
“#pragma mark -” 与下面的代码之前不要空行
遵循一般性的代码规范
7.命名规范
所有类名称以项目工程开头命名,eg:“XP”、“ZJG”、“SZ”
针对不同视图控制器,在末尾添加后缀,eg:
UIViewController 后缀添加“ViewController”
UIView 后缀添加“View”
UIButton 后缀添加“Button"
UILabel 后缀添加“Label"
8.代码量控制
单页代码最好控制在800行以内,每个方法最好不要超过80行,过多建议对代码进行重构
9.及时更新代码风格
对其他项目中copy过来的代码,根据具体需要更新代码风格,及时删除未被使用的代码
10. 及时新建目录
项目中所有Group都需要在项目目录中存在一个真实的目录,Group中的文件与真实目录中文件一一对应。
11. VC等类中的代码规范
视图控制器中相关代码的位置,按图中的位置摆放
代码示例
1.判断nil或者YES/NO
Preferred:
if (someObject) { ... }
if (!someObject) { ... }
Not preferred:
if (someObject == YES) { ...}
if (someObject != nil) { ...}
2. 条件赋值
Preferred:
result = object ? : [self createObject];
Not preferred:
result = object ? object : [self createObject];
3.初始化方法
Preferred:
NSArray *names = @[@"Brian", @"Matt", @"Chris", @"Alex", @"Steve"];
NSDictionary *productManagers = @{@"iPhone" : @"Kate", @"iPad" : @"Kamal"};
NSNumber *shouldUseLiterals = @YES;
NSNumber *buildingZIPCode = @10018;
4. 定义属性
Preferred:
@property (nonatomic, readwrite, copy) NSString *name;
1.建议定义属性的时候把所有的参数写全, 尤其是如果想定义成只读的(防止外面修改)那一定要加上readonly, 这也是代码安全性的一个习惯.
2.如果是内部使用的属性, 那么就定义成私有的属性(定义到.m的class extension里面)
3.对于拥有Mutable子类型的对象(e.g. NSString, NSArray, NSDictionary)一定要定义成copy属性. Why? 示例: NSArray的array = NSMutableArray的mArray; 如果mArray在某个地方改变了, 那array也会跟着改变.
4.尽量不要暴露mutable类型的对象在public interface, 建议在.h定义一个Inmutable类型的属性, 然后在.m的get函数里面返回一个内部定义的mutable变量.
5. BOOL赋值
Preferred:
BOOL isAdult = age > 18;
Not preferred:
BOOL isAdult;
if (age > 18) {
isAdult = YES;
} else {
isAdult = NO;
}
6. 不要使用Magic numberPreferred:
if (car == Car.Nissan)
or
const int adultAge = 18;
if (age > adultAge) {
...
}
Not preferred:
if (carName == "Nissan")
or
if (age > 18) { ... }
7.复杂的条件判断
Preferred:
if ([self canDeleteJob:job]) { ... }
- (BOOL)canDeleteJob:(Job *)job {
BOOL invalidJobState = job.JobState == JobState.New
|| job.JobState == JobState.Submitted
|| job.JobState == JobState.Expired;
BOOL invalidJob = job.JobTitle && job.JobTitle.length;
return invalidJobState || invalidJob;
}
Not preferred:
if (job.JobState == JobState.New
||job.JobState == JobState.Submitted
|| job.JobState == JobState.Expired
|| (job.JobTitle && job.JobTitle.length)) {
//....
}
清晰明了, 每个函数DO ONE THING!
8.嵌套判断
Preferred:
if (!user.UserName) return NO;
if (!user.Password) return NO;
if (!user.Email) return NO;
return YES;
Not preferred:
BOOL isValid = NO;
if (user.UserName) {
if (user.Password) {
if (user.Email) isValid = YES;
}
}
return isValid;
9. 参数过多
Preferred:
- (void)registerUser(User *user) { // to do... }
Not preferred:
- (void)registerUserName:(NSString *)userName
password:(NSString *)password
email:(NSString *)email {
// to do...
}
当发现实现某一功能需要传递的参数太多时, 就预示着你应该聚合成一个model类了...这样代码更整洁, 也不容易因为参数太多导致出错
10. 回调方法
Preferred:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
函数调用的可知性, 回调时被调用者要知道其调用者, 方便信息的传递, 所以建议在回调方法中第一个参数中加上调用者
参考文章:iOS 编程规范-ZSQ
版权属于:东哥笔记 - DongGe.org
本文链接:https://dongge.org/blog/448.html
自2017年12月26日起,『转载以及大段采集进行后续编辑』须注明本文标题和链接!否则禁止所有转载和采集行为!