前言:无规矩不成方圆,项目开发过程中,代码规范看起来是一件不起眼的事,每个接手开发的人用按照自己的一套习惯来操作命名,随着项目壮大,整体看就会感觉很乱,没有章法,让人没有欲望去了解去接手。
一个好的命名规范:代码应该简洁、易读、易懂,逻辑清晰。
核心原则:写代码不要炫技,用简单直观符合思维惯性的方式去写代码,降低别人的理解成本。
那么我们就从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相关的代码。Logic
和ViewController
的数据传递推荐使用代理
、Block
、Observer
,不可以使用通知。
5、不要在工具类里面写业务逻辑,工具类就是工具类。
6、在类的头文件中尽量少引用其他头文件,使用 @class 声明。
7、创建一个类的时候,里面默认生成的被苹果注释掉的代码,全部删掉。包括-(void)didReceiveMemoryWarning
也要删除,平时注掉不用的代码如无特殊原因,一概删除,注掉不删,要写明不能删的原因。
8、Router协议命名:KR+名称+RouterProtocolKRMineRouterProtocol
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、不要使用float
、int
定义基本类型,使用CGFloat
和NSInteger
代替,这样的好处是 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)NSString
、NSDictionary
、NSArray
使用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);
不要自己写weak
、strong
。
通知
除特殊情况下,不允许使用。
引入第三方代码
引入第三方代码要注意,必须是在社区有一定知名度,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
。
工程名字不能出现中文,不允许有空格。 工程名字采用大驼峰式命名法。
网友评论