iOS代码规范

前言:无规矩不成方圆,项目开发过程中,代码规范看起来是一件不起眼的事,每个接手开发的人用按照自己的一套习惯来操作命名,随着项目壮大,整体看就会感觉很乱,没有章法,让人没有欲望去了解去接手。
一个好的命名规范:代码应该简洁、易读、易懂,逻辑清晰。
核心原则:写代码不要炫技,用简单直观符合思维惯性的方式去写代码,降低别人的理解成本。
那么我们就从iOS常用的类、方法等一一列举。

一、资源规范

图片资源

1、(组件化开发中)各组件图片资源应该放到各自组件assets中,不允许业务新增资源丢到壳工程中
2、图片资源命名单词小写以下划线拼接如:
tabbar_mine_select

二、代码规范

类的布局

为了他人阅读你代码容易,请让你写的类按照以下方式进行布局。(⚠️注意:#pragma mark 后面有个" - ")

#pragma mark - Life Cycle
#pragma mark - Setup View / Data
#pragma mark - Observer
#pragma mark - Notification
#pragma mark - Event Response
#pragma mark - Override Methods
#pragma mark - Delegate
#pragma mark - Public Methods
#pragma mark - Private Methods
#pragma mark - Setter / Getter
#pragma mark - Network

命名
1、代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。
2、类名使用 UpperCamelCase(大驼峰命名)风格,必须遵从驼峰形式,专有名词除外:如:UDP。
3、方法名、参数名、成员变量、局部变量都统一使用lowerCamelCase(小驼峰命名)风格,必须遵从驼峰形式。
4、一个标识符的命名应该简单好懂,避免使用复杂单词。
5、viewDidLoad 和 init 方法里面不能把初始化 UI 和数据的代码混在一起,要拆成两个方法。初始化 UI 和 数据的方法放在 #pragma mark - Setup View / Data 里面,而且方法的命名应该避免使用 init、get、set
开头,建议命名:

- (void)setupViews;
- (void)setupUI;
- (void)createUI;
- (void)configData;
- (void)setupData;
- (void)fetchData;

6、当一个页面要刷新 UI 或者数据时,建议的命名是:

- (void)updateUI;
- (void)refreshUI;
- (void)reloadData;
- (void)refreshData;

7、方法命名举例: 属性/函数/参数/变量/常量/宏 的命名应该保持清晰+简洁,如果鱼和熊掌不能兼得,那么清晰更重要

Good:
insertObject: atIndex:  
removeObjectAtIndex:
removeObject: 

Bad:
insert:at:  不清晰,插入什么?at代表什么?
remove: 不清楚到底要删什么?

Good:
- (NSSize)cellSize;
- (int)runModalForDirectory:(NSString *)path file:(NSString *) name types:(NSArray *)fileTypes;
- (void)sendAction:(SEL)aSelector toObject:(id)anObject forAllCells:(BOOL)flag;

Bad:
- (NSSize)getCellSize;
- (int)runModalForDirectory:(NSString *)path andFile:(NSString *)name andTypes:(NSArray *)fileTypes;
- (int)runModalForDirectory:(NSString *)path withFile:(NSString *)name withTypes:(NSArray *)fileTypes;
- (void)sendAction:(SEL)aSelector :(id)anObject :(BOOL)flag;

1、类的命名以公司特定标识开头,比如科瑞有限公司,那么就 KR 开头(下面都用KR做例子)。
2、类名:类名的命名遵循大驼峰式命名法,类名中可以添加工程的前缀,防止多个子工程出现类名重复的情况。
3、如果是 Model必须使用 Model 结尾,View 必须是 View结尾,UIViewController VC 结尾,UITableViewController TVC结尾,UICollectionViewController CVC 结尾。
4、MVVM 中的 ViewModel以Logic 结尾,里面只能放逻辑,不能有任何 UI相关的代码。LogicViewController的数据传递推荐使用代理BlockObserver不可以使用通知。
5、不要在工具类里面写业务逻辑,工具类就是工具类。
6、在类的头文件中尽量少引用其他头文件,使用 @class 声明。
7、创建一个类的时候,里面默认生成的被苹果注释掉的代码,全部删掉。包括-(void)didReceiveMemoryWarning也要删除,平时注掉不用的代码如无特殊原因,一概删除,注掉不删,要写明不能删的原因。
8、Router协议命名:KR+名称+RouterProtocol KRMineRouterProtocol
9、【推荐】如果你重写了初始化方法,希望用调用方用你写的构造函数,那么请用:NS_DESIGNED_INITIALIZER
宏来指定调用方使用哪个初始化方法。如:

- (instancetype)initWithText:(NSString *)text NS_DESIGNATED_INITIALIZER;

10、【推荐】如果你想让调用方只使用你写构造函数,也可以用 NS_UNAVAILABLE

屏蔽系统的构造函数。如:

+ (instancetype)new NS_UNAVAILABLE;
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_UNAVAILABLE;
- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;

11、【推荐】如果你提供的方法想弃用掉,发现调用的地方比较多,一下子全改风险大,请用attribute((deprecated("已弃用, 用payWithPayInfo替换")));标明弃用,随着版本迭代逐步替换使用新方法。

方法

1、方法名的命名规范遵循小驼峰式命名法
2、要 区分方法调用和属性访问

推荐:
view.backgroundColor = [UIColor orangeColor]; 
[UIApplication sharedApplication].delegate;
不推荐:
[view setBackgroundColor:[UIColor orangeColor]]; 
UIApplication.sharedApplication.delegate;

3、方法后面的花括号不能换行。
4、单一职责原则,一个方法只干一件事情。
5、重载方法的时候,如无特殊情况均需要先调用super的方法。
6、在方法之间应该有且只有一行。这样有利于在视觉上更清晰。方法内为了视觉清晰,也酌情空行,但不要每写一行就空一行,够一个功能段空一行

分类

分类命名要用 " KR"开头,如:UIColor+KRExtensions.h,暴露出来的方法要以 "kr_"开头,如:

@interface UIColor (KRExtensions)
- (UIColor *)kr_customColor;
@end

单利

1、使用dispatch_once 来生成单例
2、单例方法命名都应该加上 shared
如: + (instancetype)defaultManager;
不知道该怎么给单例方法起名字就用:
+ (instancetype)sharedInstance;
3、【建议】如果声明了单例请用 NS_UNAVAILABLE 屏蔽掉 init 方法,如:

- (instancetype)init NS_UNAVAILABLE; 
+ (instancetype)new NS_UNAVAILABLE;

代理

1、一个类实现了那些代理,要明确的写到.m文件匿名分类的后面。苹果官方的写在前面,自定义的写在后面如:

@interface KRTopicController () <UITableViewDelegate, UITableViewDataSource, KRTopicHeaderViewDelegate>
@end

@implementation KRTopicController
@end

2、不允许这样写 self.tableView.delegate = (id)self;
这样写的坏处是:当看一个类里面的方法,发现没有地方调用,但这个方法也会走,怀疑是个代理,但看看头文件又没实现这个代理,看代码的人是很恐慌的。
3、代理一般情况下都是有两个或两个以上参数的,第一个参数返回调用代理的owner,如:

@class KRTopicHeaderView;
@protocol KRTopicHeaderViewDelegate <NSObject>
@optional
- (void) topicHeaderView:(KRTopicHeaderView *)view tapAvatar:(UIButton *)avatarBtn;
- (void) topicHeaderView:(KRTopicHeaderView *)view tapCreditScore:(UIButton *)creditScoreBtn;
@end

变量

1、变量名的命名规范遵循小驼峰式命名法(方法参数名的命名规则和变量名一致)。
2、一个变量有且只有一个功能,尽量不要把一个变量用作多种用途
3、一行声明一个变量,不要一行声明多个变量
4、少用变量标记,多用方法传值。
5、强烈建议使用枚举来定义一些变量。
6、不要使用 floatint 定义基本类型,使用 CGFloatNSInteger
代替,这样的好处是 32 位的机型 CGFloat 会转为 float,64 位的机型 CGFloat
会转为double

属性

1、变量定义,推荐用属性的方式去声明,不要用全局变量
全局变量的声明方式是MRC时代的编码风格,现在是ARC时代,不要用。要注意,属性的声明

@interface KRTopicController { 
    _varxxx; 
}
// *应该紧挨着变量名。
@interface KRTopicController () 
@property (nonatomic, strong) KRTopicHeaderView *headerView;
@property (nonatomic, strong) KRTopicFooterView *footerView;
@end

@implementation KRTopicController
@end

2、public 属性放 .h 文件里面,private 属性放 .m
文件的匿名分类里面。不要用 _xxx 的写法。
3、尽量使用不可变对象。包括:
(1)在头文件中,设置对象属性为readonly
(2)NSStringNSDictionaryNSArray 使用 copy关键字指定
(3)字典 使用 NSDictionary,而不是 NSMutableDictionary;数组 使用
NSArray,而不是 NSMutableArray
(4)向集合类型中添加元素要添加非空判断。

常量

常量定义,如果是给整个项目使用的常量定义为:
static NSString *const kSimpleString = @"simpleString";
如果只是给某个类使用的常量,定义为:
static NSString *const kClassNameConstName = @"ClassNameConstName";
宏定义和常量在 Xcode里面的显示颜色是不一样的,足以区分。当一个标识符既可以用宏定义又可以用常量的情况下首选常量。原因:常量可以在控制台打印方便调试。

宏定义

1、宏定义
#define kSafeStr(str) (([str isKindOfClass:[NSNull class]] || !str) ? @"" : [NSString stringWithFormat:@"%@", str])

小写k开头然后遵循小驼峰命名法。
2、宏定义不允许定义字符串、字面值只能用来定义代码段。

枚举

枚举定义应该使用 OC的声明方式,避免使用C的写法。定义方式如下:
typedef NS_ENUM(NSInteger, KRInformationType) {
    KRInformationLikeType = 0,// 喜欢
    KRCommentType ,// 评论
    KRMentionType ,// @
    KRSysMsgType // 系统消息
};

Block

1、调用block时需要对block判空
2、block中如果使用了self,block用 @weakify(self); Block 中使用
@strongify(self);不要自己写 weakstrong

通知

除特殊情况下,不允许使用。

引入第三方代码

引入第三方代码要注意,必须是在社区有一定知名度,github star数要够多,同一个功能的库找最多的用,必须用pod管理。有一种情况是你要做的功能就是没有知名库,但有别人已经写好的,是可以引用的,但review时会问你原因,review的人要根据他说的情况搜一下,看是不是真的没有知名库可以用。

注释

1、注释的作用:一份规范的代码必定不能缺少详尽的注释,注释的目的:方便工作交接和引导新同事熟悉代码 方便自己之后回忆代码逻辑 方便生成文档
2、注释分为单行注释和多行注释
(1)对于属性我们使用三杠 /// 进行单行注释,这样 Xcode 代码提示的时候会显示注释内容

///用户名
@property (nonatomic, copy) NSString *userName;

(2)对于特殊行//代码块注释的注释的使用双杠 //

if(orderType == JYOrderTypeNone){
    //无订单处理        
}

(3)对于方法我们使用多行注释

/** 
 * @brief 设置是否处于选中状态
 * @param selected 是否选中 
 * @param animated 是否使用动画效果 
 */ 
 - (void)setSelected:(BOOL)selected animated:(BOOL)animated;

其他

1、管理缓存使用 NSCache 而不是NSMutableDictionary,好处有一下几点:
(1)NSCache 是线程安全的,在进行多线程操作时,不需要进行加锁。
(2)NSCache在系统内存很低时会自动释放对象。
2、判断nil 或者YES/NO

正确写法:
if (someObject){ ... }
if (!someObject) { ... }
错误写法:
if (someObject == YES) { ...}
if (someObject != nil) { ...}
if (someObject == YES)容易误写成赋值语句if (someObject = YES)这样在开发的过程中不好被发现。

3、BOOL赋值正确写法:

Good:
BOOL isAdult = age > 18;

Bad:
BOOL isAdult;
if (age > 18) {
    isAdult = YES;
  } else {
    isAdult = NO;
}

4、工程名:工程名的命名必须有强烈的导向性,让人看到工程名的第一眼就明白该工程对应哪个项目。如KRUserModule
工程名字不能出现中文,不允许有空格。 工程名字采用大驼峰式命名法。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,295评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,928评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,682评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,209评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,237评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,965评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,586评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,487评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,016评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,136评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,271评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,948评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,619评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,139评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,252评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,598评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,267评论 2 358

推荐阅读更多精彩内容

  • 一、前言 本规范基于Google Objective-C Style Guide,对其中的说明性语句及非ARC部分...
    IIronMan阅读 879评论 0 6
  • iOS代码规范总结 一些原则 长的,描述性的方法和变量命名是好的。不要使用简写,除非是一些大家都知道的场景比如 V...
    ElegantLiar阅读 1,600评论 0 17
  • iOS编程规范0规范 0.1前言 为􏰀高产品代码质量,指导广大软件开发人员编写出简洁、可维护、可靠、可 测试、高效...
    iOS行者阅读 4,464评论 21 35
  • 一、命名规范 命名规则对于维护代码来说是非常重要的,。Objective-C方法名往往很长,不过这也有好处,让很多...
    jmsYang阅读 335评论 0 0
  • -------------------------------------编码原则----------------...
    yanhooIT阅读 832评论 0 11