//////////////////////////////////////////////////////////////////////
/**** 1.宏定义 ****/
说明: 宏定义在c/c++开发过程中, 能够起到简化代码, 控制代码执行, 注释, 消除警告/开启警告, 消除IDE提示错误等功能, 如非必要, 开发过程中, 应谨慎使用
另外: 宏定义一定要写于文件的开头, 如果想被外部使用, 则置于头文件, 如果仅仅本类使用则置于实现文件
<1>与Cocoa Touch相关的核心基础库相关, 用于全局代码层次上的宏定义
使用核心基础库的前缀, 采用驼峰命名法, 并且宏定义应简洁明了, 如颜色宏
define UIColorRGB(red, green, blue) [UIColor colorWithRed:(red) green:(green) blue:(blue) alpha:1.0f]
<2>单独文件使用的宏定义同样采用驼峰命名法, 但是要在前面添加’k’例如 布局UI时, 想定义一个间距为20
define kLayoutMargin 20
功能: 便于修改, 避免代码写死, 修改起来还要找到固定的代码行
<3>如果想利用宏定义控制某些环境变量, 或者开关之类, 使用_命名法, 并且首个单词必须交代清楚作用(可用大家都能懂的缩写)
如: 测试环境 #define ENV_DEVELOPMENT 1 生产环境 #define ENV_DISTRIBUTION 1
<4>功能类宏定义
功能1: 字符串宏定义 #define STR_Search @“搜索”
功能2: 图标类宏定义 #define ICON_Search @“search.png”
功能3: 字典key值宏定义 #define KEY_Anyone @“anyone”
功能4: 网络请求URL宏定义 #define URL_GetUserList @“http://10.110.20.23:80/getUserList/index.html”
功能5: 单例类宏定义 #define SINGLTON_User [User defaultUser]
//////////////////////////////////////////////////////////////////////
/**** 2.全局变量 ****/
说明: 全局变量在oc/c++开发中, 同样有着至关重要的作用, 但是oc可以使用单例类来实现全局变量的作用, 但也不免排除有些开发者直接使用全局变量
注意:
<1>.命名规则: 使用驼峰命名法, 前缀为XM, 第一个单词简要的具体说明性质
例如: BOOL型全局变量为进入后台 BOOL XMEnterBackground = NO;
例如: 通知名称 NSString *XMNotificationReceiveAddressbookRefresh = @“XMNotificationReceiveAddressbookRefresh”;
<2>.所有全局变量的初始化, 应放于实现文件, 如果使用的话, 可以在其头文件利用extern 函数, 例如: extern NSString *XMNotificationReceiveAddressbookRefresh;
<3>.当然开发人员也可以使用其他修饰词, 如果你不想改变全局变量的值则可以 extern const NSString *XMNotificationReceiveAddressbookRefresh;
//////////////////////////////////////////////////////////////////////
/**** 3.文件命名规则 ****/
说明: 文件的命名规则也同样重要, 除category以外, 有所的文件命名应为 前缀 XMxxxx.h XMxxxx.m XMxxxx.xib
注意:
<1>.使用xib时吗xib的文件名要头文件, 实现文件一样
<2>.文件的命名规则, 也应遵守驼峰命名法, 并且第一个单词尽量简单明了说明类的作用是什么
例如:通讯录控制器 XMAddressbookViewController.h
菜单视图 XMMenuView.h
联系人模型 XMContactModel.h
<3>.所创建类头文件, 应将作者信息, 创建时间, 最近修改, 主要功能填写清楚
<4>.个人封装的视图, 切忌与其他的文件耦合性太高, 应尽量注重代码可移植性, 代码可重用性, 代码可维护性等多方面考虑, 如何封装
模板:
//
// XMDetailConferenceViewController.h
// 功能: 会议详情页的展示功能 (控制器)
// 作者: xx
// 创建日期: 2015-12-27
// 最近修改: 2016-10-13
//
//////////////////////////////////////////////////////////////////////
/**** 4.图片资源命名规则 ****/
说明: 开发人员可能会根据UI视觉设计布局页面, 有些页面需要使用大量的切图, 而图片的命名, 也同样要有规范
注意:
<1>.公用图片要根据用途命名, 但要注意区分不同的状态 (普通: normal 高亮: highlight 选中: selected), 命名格式icon_xxxxx(用途)_xxxx(区分)_normal(状态).png
例如:
tab页签的图片: icon_tabbar_addressbook_normal@2x.png icon_tabbar_addressbook_selected@2x.png icon_tabbar_addressbook_highlight@2x.png
导航返回的图片:icon_navgationBar_back_normal@2x.png icon_navgationBar_back_selected@2x.png icon_navgationBar_back_highlight@2x.png
<2>.非公用图片, 命名格式xxxx(控制器/视图名)_xxxxx(用途)_xxxx(区分)_normal(状态).png
例如: 通讯录控制器, 搜索按钮: addressbook_btn_search_normal@2x.png
命名规则前缀英文或者拼音不做限制, 应简洁明了, 通俗易懂, 例如icon_erweima.png(二维码) 都可以
//////////////////////////////////////////////////////////////////////
/**** 5.重定义枚举类型书写规范 ****/
说明: 在发开过程中, 某些类需要支持不通的属性, 例如, 一个会议详情页面, 需要根据model的不同, 从而展示不通的提示
如果用int 0, 1, 2也可以, 但是不好区分, 也不好维护, 那么定义枚举就能很方便的阅读代码
注意: 定义枚举, 枚举的前缀一定是 你重定义的别名 例如XMDetailConferenceType+xxx, 如下
typedef enum : NSUInteger {
XMDetailConferenceTypeOnMeeting,
XMDetailConferenceTypeWillBegin,
XMDetailConferenceTypeEnd,
} XMDetailConferenceType;
//////////////////////////////////////////////////////////////////////
/**** 6.代码书写规范 ****/
说明: 开发人员有个良好的代码书写规范, 对维护代码有着重要的意义
<1>.成员变量书写规范
成员变量, 分为三种类型 @private @public @protected, 开发人员可酌情使用修饰词, 成员变量应如下做出注释
注意: 成员变量一定要写成 _xxx 格式, for大家的良好编码习惯, 模仿苹果工程师才是正确的选择
例如:
@interface NSThread : NSObject {
@private
id _private; //私有
uint8_t _bytes[44]; //字节数
}
<2>.属性书写规范
通常属性应置于成员变量之下, 方法之上的位置, 开发人员可酌情使用属性修饰词, 但是注意ARC工程的属性修饰词应尽量使用strong或者weak, 属性也要明确的注释
注意: 为了代码美观, 开发人员尽量将其对其(不强制), 驼峰命名法, 简洁明了
例如:
//菜单颜色
@property (nonatomic, strong) UIColor *menuColor;
//代理
@property (nonatomic, weak) id<LYMenuViewDelegate> delegate;
或者
/菜单颜色/
@property (nonatomic, strong) UIColor *menuColor;
/代理/
@property (nonatomic, weak) id<LYMenuViewDelegate> delegate;
<3>.方法书写规范
方法书写规范也应当简单明了, 英文与拼音不做要求限制, 驼峰命名法
动态方法 书写规范:- (返回值)方法名:(参数类型)形参 方法名:(参数类型)形参{
}
静态方法 书写规范:+ (返回值)方法名:(参数类型)形参 方法名:(参数类型)形参{
}
方法体内, 至少方法和方法体内间隔空一行
以表格视图为例
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
//编写方法体, 方法体与方法名需空一行
return 1;
}
<4>.条件语句书写规范
条件语句即所谓的if else, switch case, 书写这类语句时, 注意对其方式, 以及大括号位置
特别注意: 在这里切记将大括号至于if语句下面, 因为如果代码行数较多的情况下, 条件语句嵌套使用, 开发人员很难找到对应的条件语句大括号, 而且嵌套使用, 应该错位, 见2的操作
- 当判断一个变量为简单类型数据时, 例如判断a = 1
规范为 if (1 == a){ 一定要把简单数据类型放在左边, 因为假如你少写了=, 条件语句即为赋值语句, 条件总是为真, 则会引发预想不到的后果, 但是将一个变量赋给一个简单类型的数字, IED会提示错误
//to do
}
-
switch(a){
case: 1{ 如果switch嵌套条件语句, 则
if (YES){
// to do
}
}
break;case: 2 如果不嵌套, 随意使用
break;default: 注意default可以省略, 如果case在配和枚举使用考虑完全的话
break;
}
<5>.控制流书写规范
控制流即为循环语句 while, for, forin, do-while
注意书写格式, 任然是大括号的问题, 推荐以下写法
例如:
int a = 0;
while(a < 10){
//至少与控制流语句空一行
a++;
}
例如:
int a = 0;
do{
//至少与控制流语句空一行
a++;
}while(a < 10);
注意:无论for还是while开发人员应该特别注意循环条件, 避免循环一直执行
<6>.协议书写规范
首先: 协议的命名, 如果在本类中应命名为 xxxx(类名)Delegate, 例如: @protorl XMMenuViewDelegate <NSObject>
开项目开发过程中, 协议必然会用到, 代理设计模式有着很大的用途, 例如: 回调方法, 反向传值, 解耦等等
注意: 协议方法如果写的过于简单的话, 开发人员容易将其认为是本类的方法, 为了便于区分, 建议大家沿着苹果工程师的规范书写协议方法, 协议的功能应当给出注释, 英/中文不限
例如: - (返回值)类:(本类型)本类参数 方法名:(类型)形参;
@protocol LYMenuViewDelegate <NSObject>
@required
//protocol must be implementation
- (void)menuView:(LYMenuView *)view tableView:(UITableView *)tableView didSelectedRowAtIndexPath:(NSIndexPath *)indexPath dataSource:(LYMenuViewDataSource *)dataSource;
@end
这点上模仿苹果, 如表格视图的代理方法:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
<7>.空行规范
说明: 在书写代码的时候, 空行规范也是一定要有
例如: 算数表达式 a = b + c;
格式: a(空行)=(空行)b(空行)+(空行)c;
例如: 定义变量: int a = 10;
例如: 书写方法时, 空行规范
格式: -(空行)(返回值)类:(类型)本类参数(空行)方法名:(类型)形参;
如果类型为一直对象, 那么 类型 即可 拆分为 类名+(空行)+(*)
即: - (void)tableView:(UITableView *)tableView;
//////////////////////////////////////////////////////////////////////
/**** 7.方法书写需要注意的事项 ****/
说明: 如果方法所占用的代码行数超过200行, 开发人员就要想办法, 将其方法从大括号里分离出几个简单的方法, 嵌套方法使用, 避免方法体太多, 导致看其代码眼花缭乱
举个例子
-
(void)testLargeMethod{
int state = [User getState];
if (1 == state) {for(id object in _array1){
NSLog(@“%@”, object);
}}else if (2 == state) {
for(id object in _array2){
NSLog(@“%@”, object);
}}else if (3 == state) {
for(id object in _array3){
NSLog(@“%@”, object);
}}else if (4 == state) {
for(id object in _array4){
NSLog(@“%@”, object);
}}else if (5 == state) {
for(id object in _array5){
NSLog(@“%@”, object);
}}
}
这样看起来很繁琐的代码, 而且又有赘余的代码, 则完全可以拆分
例如: -
(void)testLargeMethod{
int state = [User getState];
NSArray *temp = nil;if (1 == state) {
temp = _array1;
}else if (2 == state) {
temp = _array2;
}else if (3 == state) {
temp = _array3;
}else if (4 == state) {
temp = _array4;
}else if (5 == state) {
temp = _array5;
}[self printObjectFromArray:temp];
} (void)printObjectFromArray:(NSArray *)array{
for(id object in _array1){
NSLog(@“%@”, object);
}
}
//////////////////////////////////////////////////////////////////////
/**** 8.编码格式 ****/
说明: 编码格式对于提高阅读代码效率, 快速理清代码思路有着很大帮助, 开发人员应考虑除自己阅读以为, 其他同事还有可能阅读你的代码, 从而考虑, 从代码思想上, 代码层次, 以及代码质量上严格要求自己
举个例子, 一段编码习惯良好的代码, 阅读起来非常方便
@prmga mark - 测试方法
-
(void)testMethod{
//获取状态
int state = [User getState];if (1 == state) { 为了便于阅读, 每个方法完毕, 空一行
temp = _array1;
}else if (2 == state) {
temp = _array2;
}else if (3 == state) {
temp = _array3;
}else if (4 == state) {
temp = _array4;
}else if (5 == state) {
temp = _array5;
}//遍历数组的结果 适当的添加注释, 使得开发就是那么的简单 -_-
[self printObjectFromArray:temp];
}
//////////////////////////////////////////////////////////////////////
/**** 9.不寻常的引用问题 ****/
举个例子: 大家都注意下, block很容易引发循环引用问题
@property (nonatomic, copy) void(^objBlock)(id obj);
(void)test{
NSLog(@"%s", func);
}-
(void)implementBlock{
错误的写法: 导致循环引用
self.objBlock = ^void(id obj){ 第一种写法 此种写法分析: self持有block, block体内部又对self增加了一个引用, 形成引用闭环, 即所谓的循环引用[self test];
};
正确的写法, 不会导致循环引用
__weak Model *wself = self; 第二种写法 此种写法不会对self持有引用, 因为__weak的实现:
self.objBlock = ^void(id obj){ weak表示的是一个弱引用,这个引用不会增加对象的引用计数,并且在所指向的对象被释放之后,weak指针会被设置的为nil
具体原理很复杂, 不在此分析, 只是提醒注意下
__strong Model *sself = wself;
[sself test];};
}
//////////////////////////////////////////////////////////////////////
/**** 10.代码优化 ****/
说明: 开发过程中, 我们接受的模块可能是其他人新写的, 也可能是年头比较陈旧的老代码, 如果阅读起来很困难
建议:
<1>.某块方法代码赘余, 或者实现方式有点繁琐, 思路不清晰, 有可能引发问题的代码, 开发人员可以在排期时间内, 将此代码优化的时间也一起添加进去.
<2>.某个类总体实现思路有问题, 或者以上等等, 在不影响项目该模块的功能和排期的情况下, 建议重写模块, 重构逻辑, 重构中, 优化代码
//////////////////////////////////////////////////////////////////////
/**** 11.代码注释规范 ****/
说明: 凡是创建的文件, 头文件暴露出来的方法都需要添加注释, 无论简单与否, 实现文件, 每个方法也应有注释, 必要的代码逻辑也需要注释
<1>.创建头文件注释规范, 详细见 //3.文件命名规则
<2>.属性, 成员变量注释, 详细见 //6.代码书写规范
<3>.方法注释, 例如
方式1:
/**
- 实现block
- @param arg 所传递的参数
*/
-
(void)implementBlock:(id)arg{
//弱引用
__weak Model *wself = self;
self.objBlock = ^void(id obj){//强引用
__strong Model *sself = wself;
[sself test];};
}
方式2:
@pragm mark - 实现block
-
(void)implementBlock:(id)arg{
//弱引用
__weak Model *wself = self;
self.objBlock = ^void(id obj){//强引用
__strong Model *sself = wself;
[sself test];};
}
方式三:
// 实现block
-
(void)implementBlock:(id)arg{
__weak Model *wself = self; //弱引用
self.objBlock = ^void(id obj){__strong Model *sself = wself; //强引用 [sself test];
};
}
方法注释多样保证对齐, 明显, 言简意赅, 中英文不做限制, 但为了保证其他人能看懂, 应尽量使用中文注释
//////////////////////////////////////////////////////////////////////
/**** 12.有关于代码重用 ****/
以工程中的相关代码举例.
类似XMSearchGroupProtraitView自定义试图.在群组列表以及最近通讯cell中使用到.但是此控件却仅是XMSearchGroupCell类中声明的全局变量.类似此类多出使用到的控件,请在CustomView文件分类中单独写出一个类来使用.因为在最近通讯cell中使用的仅是一个XMSearchGroupProtraitView控件而不是一个cell.
单独仅用一次的控件、对象可以在你自己类中单独去写,工程中统一用到的一定要统一起来.
//////////////////////////////////////////////////////////////////////
/**** 13.有关于资源文件的存放 ****/
1、例如图片资源文件,首先在最新的recourse文件夹中寻找你需要添加图片的分类,然后再去添加图片.
2、第三方库文件,第三方库相关文件资源统一在ThirdPart<第三方框架>文件夹中存放
3、所有创建的新类、在本地文件夹中的层级关系要与工程中的一致