2020-09-14
# **一、运算符**
### **1.运算符与变量之间的间隔 :**一元运算符与变量之间没有空格:
```
!bValue
~iValue
++iCount
*strSource
&fSum
```
#### **2.二元运算符与变量之间必须有空格**
```
fWidth = 5 + 5;
fLength = fWidth * 2;
fHeight = fWidth + fLength;
for(int i = 0; i < 10; i++)
```
#### **2.三元运算符,变量之间必须有空格**
```
fWidth = num > 5 ? 375 : 400;
```
### **4.多个不同的运算符同时存在时应该使用括号来明确优先级**
在多个不同的运算符同时存在的时候应该合理使用括号,不要盲目依赖操作符优先级。 因为有的时候不能保证阅读你代码的人就一定能了解你写的算式里面所有操作符的优先级。
```
num = a - c / d + e;
num = a - (c / d) + e;
```
# **二、大括号用法**
### 1.条件语句
```
if (count < 3)
{
page = 1;
}else if (count > 3)
{
page = 2;
}else
{
page = 3;
}
```
- **条件表达式如果很长,则需要将他们提取出来赋给一个BOOL值**
```
let nameContainsSwift = sessionName.hasPrefix("Swift")
let isCurrentYear = sessionDateCompontents.year == 2014
let isSwiftSession = nameContainsSwift && isCurrentYear
if (isSwiftSession)
{
// Do something
}
```
不推荐这样写:
```
if ( sessionName.hasPrefix("Swift") && (sessionDateCompontents.year == 2014) ) {
// Do something
}
```
- **每个分支的实现代码都必须被大括号包围**
```
if (!error)
{
return success;
}
```
不推荐这样写:
```
if (!error) return success;
```
## **2.switch**
每个分支都必须用大括号括起来
```
switch (count)
{
case 0:
{
page = 1;
break;
}case 1:
{
page = 2;
break;
}
default:
break;
}
```
## 3.函数
```
- (void)loadData
{
//code
}
```
注意:方法参数对齐
```
//一行可以显示不进行换行
- (void)loadDataInTable:(UITableView *)tableView params:(NSDictionary *)params
{
//code
}
//多行冒号对齐
- (void)loadDataInTable:(UITableView *)tableView
params:(NSDictionary *)params
succeed:(void(^)(DTHomeIndexModel *model))succeed
{
//code
}
//多行长参数名 ,居左对齐
- (void)loadDataInTable:(UITableView *)tableView
myVeryVeryLongLongLongParams:(NSDictionary *)params
succeed:(void(^)(DTHomeIndexModel *model))succeed
{
//code
}
```
# 三、**注释**
### **1.属性注释**
\*\*\*\*放在属性上方
```
@interface GJRVipPayTypeModel : NSObject
//0 匠币 1 微信 2 支付宝 3 苹果支付
@property (nonatomic, assign) NSInteger payType;
//支付名称
@property (nonatomic, copy) NSString *name;
//是否推荐 0 不推荐 1推荐
@property (nonatomic, assign) NSInteger recommend;
#pragma mark - 自定义
//是否匠币
@property (nonatomic, assign) BOOL gjr_isCoinPay;
@end
```
### 2.示例注释
如对外api提供调用接口,如比较复杂,需提供调用示例
```
/*
*示例
GJRAlert * alert = [[GJRAlert alloc]initTitle:@"提示" content:@"描述内容" cancelTitle:@"取消" cancelAction:^{
} confirmTitle:@"确定" confirmAction:^{
}];
// alert.isAutoHideAlert = NO;
[alert show];
*/
```
### 3.函数名注释
```
/// 提交购买会员
/// @param vipType vip类型 (0:招标会员,1:gps会员)
/// @param payType 支付类型 (0:苹果支付,1微信支付,2支付宝支付)
/// @param paySucceed 支付成功
/// @param payFailure 支付失败
- (void)openVipWithVipType:(NSInteger)vipType
payType:(NSInteger)payType
paySucceed:(void(^)(void))paySucceed
payFailure:(void(^)(void))payFailure;
```
## 4.条件注释
统一放在条件右侧
```
if (count < 3) //小于3
{
page = 1;
}
switch (count) {
case 0: //等于0
{
page = 1;
break;
}
default:
break;
}
```
### 5.其他注释
```
// TODO: 等待实现
// FIX: 有bug,需要修改
// !!!: 逻辑混乱,需要完善
- (NSInteger)sumNumber:(NSInteger)firstNumber withNumber:(NSInteger)secondNumber;
```
# 四、**命名规范**
## **1.变量**
### **变量名必须使用驼峰格式**
类,协议使用大驼峰,前缀添加GJR:
```
GJRHomePageViewController.h
<GJRHeaderViewDelegate>
```
对象等局部变量使用小驼峰:
```
NSString *personName = @"";
NSUInteger totalCount = 0;
```
### **变量的名称必须同时包含功能与类型**
```
UIButton *addBtn //添加按钮
UILabel *nameLab //名字标签
NSString *addressStr//地址字符串
```
### **系统常用类作实例变量声明时加入后缀**
| 类型 | 后缀 |
|:----|:----|
| UIViewController | ViewController |
| UIView | View |
| UILabel | Lab |
| UIButton | Btn |
| UIImage | Img |
| UIImageView | ImageV |
| NSArray | Array |
| NSMutableArray | MuArray |
| NSDictionary | Dic |
| NSMutableDictionary | MuDic |
| NSString | Str |
| NSMutableString | MuStr |
| NSSet | Set |
| NSMutableSet | MuSet |
## **2.常量**
### **常量以相关类名作为前缀**
推荐这样写:
```
static const NSTimeInterval GJR_LOGIN_TIMEOUT = 30;
```
不推荐这样写:
```
static const NSTimeInterval fadeOutTime = 0.4;
```
### **建议使用类型常量,不建议使用#define预处理命令**
```
static NSString * const GJR_ORDER_TITLE = @"订单";
static const CGFloat GJR_ORDER_IMG_HEIGHT = 50.0f;
```
不推荐这样写:
```
#define Title @"订单"
#define ImgHeight 42
```
## **3.宏**
### **宏、常量名都要使用大写字母,前缀添加GJR,用下划线‘\_’分割单词。**
```
#define GJR_GET_ORDER_PAYSTATUS @"order/items/getPayInfo" //url宏规则:GJR_请求方式_模块_接口功能
#define GJR_BOLD_FONT(fontSize) [UIFont boldSystemFontOfSize:fontSize]
#define GJR_SCREEN_WIDTH 375.00
extern const NSString GJR_USER_AGE_KEY = @"123456";
```
### **宏定义中如果包含表达式或变量,表达式和变量必须用小括号括起来。**
```
#define GJR_MIN(A, B) ((A) > (B) ? (B) : (A))
```
## **4.属性**
### **1属性的命名使用小驼峰**
推荐这样写:
```
@property (nonatomic, strong) UIButton *confirmBtn;
```
### **属性的关键字推荐按照 原子性,读写,内存管理的顺序排列**
推荐这样写:
```
@property (nonatomic, readwrite, copy) NSString *name;
@property (nonatomic, readonly, copy) NSString *gender;
@property (nonatomic, readwrite, strong) UIView *headerView;
```
注意:空格位置
```
@property□(nonatomic,□strong)□UIButton□*confirmBtn;
```
## **5.方法**
### **方法名中不应使用and,而且签名要与对应的参数名保持高度一致**
推荐这样写:
```
- (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height;
```
不推荐这样写:
```
- (instancetype)initWithWidth:(CGFloat)width andHeight:(CGFloat)height;
```
```
- (instancetype)initWith:(int)width and:(int)height;
```
### **方法名前缀**
推荐这样写:
```
- (void)init...//初始化 - (void)initViews 初始化UI
- (void)update...;//更新 - (void)updateData - (void)updateTitleFrame
- (void)do...Action;//点击事件 do+事件+Action - (void)doSubmitAction
- (void)load...; //请求数据
- (BOOL)is... //方法返回值为boolean型的请使用is前缀标识
- (UIView *)get... //返回某个值的方法,使用get为前缀标识
- (UIView *)set... //设置...
- (void)save... //保存数据
- (void)clear... //清除数据
- (NSString *)gjr_...;//分类中方法添加gjr_前缀
```
# 四、类
### **1.遵循代理过多的时候,换行对齐显示**
```
@interface GJROrderViewController () <UIGestureRecognizerDelegate>
//过多代理
@interface GJROrderViewController ()
<
UIGestureRecognizerDelegate,
HXSClickEventDelegate,
UITableViewDelegate,
UITableViewDataSource
>
```
### **2. 在类的头文件中尽量少引用其他头文件**
有时,类A需要将类B的实例变量作为它公共API的属性。这个时候,我们不应该引入类B的头文件,而应该使用向前声明(forward declaring)使用class关键字,并且在A的实现文件引用B的头文件。
**3. 类的布局**
```
#pragma mark - ——————————————————— LifeCycle ———————————————————
- (void)dealloc
{
}
- (void)viewDidLoad
{
}
- (void)viewDidAppear:(BOOL)animated
{
}
- (void)didReceiveMemoryWarning
{
}
#pragma mark - ————————————————— init and config ——————————————
#pragma mark - ———————————————————— Override —————————————————
#pragma mark - ————————————— Net Connection Event ————————————
#pragma mark - ——————————————— Private Funcation ———————————————
#pragma mark - ——————————————— Public Funcation ———————————————
#pragma mark - —————————————— Notifation Funcation ——————————————
#pragma mark - —————————————————— Touch Event —————————————————
#pragma mark - ————————————————— Delegate Event ———————————————
#pragma mark - ————————————————— Setter/Getter ————————————————
```
# 五、**字面量语法**
尽量使用字面量值来创建 NSString , NSDictionary , NSArray , NSNumber 这些不可变对象:
推荐这样写:数量多是对齐分行显示
```
NSArray *names = @[
@"Brian",
@"Matt",
@"Chris",
@"Alex",
@"Steve",
@"Paul"
];
NSDictionary *productManagers = @{
@"iPhone" : @"Kate",
@"iPad" : @"Kamal",
@"Mobile Web" : @"Bill"
};
```
不推荐这样写:
```
NSArray *names = [NSArray arrayWithObjects:@"Brian", @"Matt", @"Chris", @"Alex", @"Steve", @"Paul", nil];
NSDictionary *productManagers = [NSDictionary dictionaryWithObjectsAndKeys: @"Kate", @"iPhone", @"Kamal", @"iPad", @"Bill" ];
```
# 六、枚举
所属类名(GJROrder)+枚举类别名(state)+类型(UnStart)
```
//订单任务类型
typedef NS_ENUM(NSUInteger, GJROrderState)
{
GJROrderStateUnStart = 0, //未开始
GJROrderStateProgress, //进行中
GJROrderStatecomplete //已完成
};
```
# **六、安全处理**
建议在定义NSArray和NSDictionary时使用类型标注,可以保证程序的安全性:
```
@property (nonatomic, strong) NSArray <GJRVipPayTypeModel *> *payTypesArr;
```
向代理或block发送消息时需要判断其是否实现该方法
```
if ([self.delegate respondsToSelector:@selector(signUpViewControllerDidPressSignUpButton:)])
{
[self.delegate signUpViewControllerDidPressSignUpButton:self];
}
if(self.finishBlock)
{
self.finishBlock();
}
```
Block引用-外部弱引用,内部使用强引用
```
__weak __typeof__(self) weakSelf = self;
cell.payTypeChangedBlock = ^(NSArray<GJRVipPayTypeModel *> * _Nonnull listModel) {
__strong __typeof(self) strongSelf = weakSelf;
[strongSelf doSomething];
[strongSelf doOtherThing];
};
```
数值读取需进行安全处理
```
NSString* str = gjr_str_protect(model.itemsCode);
NSArray *data = gjr_dic_getValidObject(resultData, @"data");
ListModel*model = gjr_arr_getValidObject(self.dataArray, 0)
```