专栏首页工匠人工匠人iOS 代码规范
原创

工匠人iOS 代码规范

一、运算符

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)

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

相关文章

  • Android官方MVP架构项目解析

    前段时间Google在Github开源了一个项目Android Architecture Blueprints,在项目中展示了使用不同的实现架构和工具来实现相同...

    用户2802329
  • 【专业技术第十二讲】void的妙用

    存在问题: 遇到微信好友询问关于void *的用法,这里做一个总结性的回复。 解决方案: void的字面意思是空类型,void *的意思是空类型指针,void ...

    程序员互动联盟
  • CVE-2019-2725/CNVD-C-2019-48814终章——报文回显

    这是一款很神奇的工具。神奇在运行它可以得到回显且能找到正确的webapp发布路径,目前已知的xmldecoder的exp一般都是写webapp默认路径。当用户安...

    洛米唯熊
  • C++核心准则​NL.25:不要将void用作参数类型

    It's verbose and only needed where C compatibility matters.

    面向对象思考
  • Android基于IJKPlayer视频播放器简单封装设计

    我们都知道需要播放一个视频需要三个过程 1.create MediaPlayer 2.MediaPlayer prepare 3.MediaPlayer 与 S...

    砸漏
  • Qt编写自定义控件7-自定义可拖动多边形

    自定义可拖动多边形控件,原创作者是赵彦博(QQ:408815041 zyb920@hotmail.com),创作之初主要是为了能够在视频区域内用户自定义可拖动的...

    feiyangqingyun
  • Qt编写自定义控件36-图片浏览器

    本控件主要用来作为一个简单的图片浏览器使用,可以上下翻页显示图片,图片还可以开启过度效果比如透明度渐变,应用场景有查看报警图片运行图片等。此控件非本人原创,来源...

    feiyangqingyun
  • iOS开发-AFNetworking详解

    这是一篇AFNetworking的详细解析 使用示例 新建一个AFHTTPSessionManager的manager,然后用manager请求对应网址的信息,...

    落影
  • struct sqlite3

    {   sqlite3_vfs *pVfs;            /* OS Interface */   struct Vdbe *pVdbe;      ...

    py3study
  • C++使用初始化列表的方式来初始化字段

    明白了上述用法以后,Android Recovery源代码里面也有类似的案例。下面这个是Recovery的一个构造函数,代码位于:screen_ui.cpp...

    morixinguan

扫码关注云+社区

领取腾讯云代金券