公司外包项目日渐增多,为了规范项目代码风格使项目易于维护和交叉开发,以下规定相关规范要求,我们把开发规范暂时划分成两个等级,分别是【必须】、【建议】。
【必须】项目宏和字符常量的命名
//通用宏定义 以小写k开头的驼峰法命名
#define kBaseServerURL @"xxxxx"
//NSUserDefault 的Key 必须以UDKey_开头
UDKey_LoginUserInfo
//NSNotification 的key 必须以NNKey_开头
NNKey_UserStatusChanged
//类型枚举以Ty开头
typedef NS_ENUM(NSInteger, TyPayWay) {
TyPayWayUnion = 1, //银行卡支付
TyPayWayAlipay, //支付宝支付
TyPayWayCoin, //积分支付
TyPayWayWechat //微信
};
//全局prompt提示语宏定义,以kPrompt_开头
#define kPrompt_Timeout @"网络连接超时,等会儿再试试…"
【必须】自我描述性。属性/函数/参数/变量/常量/宏 的命名必须具有自我描述性。杜绝过度缩写、或者无意义的命名方式。
【必须】驼峰命名方式。参数名、成员变量、局部变量、属性名都要采用小写字母开头的驼峰命名方式。
如果方法名以一个众所周知的大写缩略词开始,可以不适用驼峰命名方式。比如FTP、WWW等。
如果Model类中因为服务端参数以【xxx_xxxx】方式命名,为了快速开发实现Model迭代可以跟服务端返回参数一样。
【必须】清晰性。属性/函数/参数/变量/常量/宏 的命名应该保持清晰+简洁,如果鱼和熊掌不能兼得,那么清晰更重要。
命名 | 说明 |
---|---|
insertObject:atIndex: | 规范的写法 |
insert:at: | 不清晰,插入什么?at代表什么? |
removeObjectAtIndex: | 规范的写法 |
removeObject: | 规范的写法,因为参数指明了要移除一个对象 |
remove: | 不清晰,移除什么? |
【建议】一般情况下,不要缩写或省略单词,建议拼写出来,即使它有点长。当然,在保证可读性的同时,for循环中遍历出来的对象或者某些方法的参数可以缩写。
命名 | 说明 |
---|---|
destinationSelection | 规范写法 |
destSel | 不清晰 |
setBackgroundColor : | 规范写法 |
setBkgdColor: | 不清晰 |
【必须】方法名也要采用小写字母开头的驼峰命名方式。如果方法名以一个中所周知的大写缩略词开头(比如HTTP),该规则可以忽略。
【建议】一般情况下,不要在方法名称中使用前缀,因为他存在于特定类的命名空间中。
【必须】禁止在方法前面加下划线“ _ ”。Apple官网团队经常在方法前面加下划线"_"。为了避免方法覆盖,导致不可预知的意外,禁止在方法前面加下划线。
【必须】自我描述性。方法的命名也应该具有自我描述性。杜绝过度缩写、或者无意义的命名方式。
【必须】苹果爸爸说:如果一个方法代表某个名词执行的动作,则该方法应该以一个动词开头。如下:
- (void)invokeWithTarget:(id)target;
- (void)selectTabViewItem:(NSTabViewItem *)tabViewItem
【必须】不要使用“do”或者"does"作为方法名称的一部分,因为这些助动词不能为方法名称增加太多的意义,反而让方法看起来更加臃肿。同时,也请不要在动词前面使用副词或者形容词。
【建议】参数之前的单词尽量能描述参数的意义。
命名 | 说明 |
---|---|
- (id)viewWithTag:(NSInteger)aTag; | OK |
- (id)taggedView:(int)aTag; | 不OK |
【必须】category中不要声明属性和成员变量。
【必须】避免category中的方法覆盖系统方法。可以使用前缀来区分系统方法和category方法。但前缀不要仅仅使用下划线”_“。
【建议】如果一个类比较复杂,建议使用category的方式组织代码。具体可以参考UIView。
#pragma mark - Lifecycle
- (instancetype)init {}
- (void)dealloc {}
- (void)viewDidLoad {}
- (void)viewWillAppear:(BOOL)animated {}
#pragma mark - LoadData
- (void)loadData {}
- (void)loadMoreData{}
#pragma mark - Public
- (void)publicMethod {}
-
#pragma mark - Private
- (void)privateMethod {}
#pragma mark - IBActions
- (IBAction)submitData:(id)sender {}
#pragma mark - UITableViewDataSource
#pragma mark - UITableViewDelegate
#pragma mark - OtherDelegate
#pragma mark - Get & Set
- (void)setCustomProperty:(id)value {}
- (id)customProperty {}
#pragma mark - NSObject
- (NSString *)description {}
【必须】UIViewController生命周期相关方法一定要放在最上面,不能中间插入自定义方法。
【必须】UIViewController方法要分门别类并使用mark标记区分。#pragma mark - life style
【必须】公有属性写在.h文件中,私有属性写在.m文件的扩展interface中。
【必须】调用block时需要对block判空。
【必须】注意block潜在的引用循环。
【必须】在每个应用中,我们应该时刻留意并控制通知的数量,避免通知满天飞的现象。当我们使用通知时,必须要思考,有没有更好的办法来代替这个通知。禁止遇到问题就想到通知,把通知作为备选项而非首选项。
【必须】post通知时,object通常是指发出notification的对象,如果在发送notification的同时要传递一些额外的信息,请使用userInfo,而不是object。
【必须】在多线程应用中,Notification在哪个线程中post,就在哪个线程中被转发,而不一定是在注册观察者的那个线程中。如果post消息不在主线程,而接受消息的回调里做了UI操作,需要让其在主线程执行。
【必须】类属性中的IBOutlet属性应该能一下子提现出所属UI类,比如
titleLabel
shareButton
avatarImageView
nameTextfield
contentTextView
【必须】如果想要获取window,不要使用view.window获取。请使用[[UIApplication sharedApplication] keyWindow]。
【建议】当访问一个CGRect的x,y,width,height时,应该使用CGGeometry函数代替直接访问结构体成员。
因此,推荐的写法是这样的:
CGRect frame = self.view.frame;
CGFloat x = CGRectGetMinX(frame);
CGFloat y = CGRectGetMinY(frame);
CGFloat width = CGRectGetWidth(frame);
CGFloat height = CGRectGetHeight(frame);
反对这样的写法:
CGRect frame = self.view.frame;
CGFloat x = frame.origin.x;
CGFloat y = frame.origin.y;
CGFloat width = frame.size.width;
CGFloat height = frame.size.height;
【必须】如果方法、函数、类、属性等需要提供给外界或者他人使用,必须要加注释说明。
【必须】如果你的代码以SDK的形式提供给其他人使用,那么接口的注释是必须的。必须对暴露给外界的所有方法、属性、参数加以注释说明。
【建议】注释应该说明其作用以及注意事项(如果有)。
【建议】因为方法或属性本身就具有自我描述性,注释应该简明扼要,说明是什么和为什么即可。
【建议】尽量减少继承,类的继承关系不要超过3层。可以考虑使用category、protocol来代替继承。
【建议】把一些稳定的、公共的变量或者方法抽取到父类中。子类尽量只维持父类所不具备的特性和功能。
【建议】.h文件中只暴露出一些必要的类、公开的方法、只读属性;私有类、私有方法和私有属性以及成员变量,尽量写在.m文件中。