代码规范是我们从入行至今,一直都在遵守的一个规范。当然这个规范没有什么明文的规定,可以是公司内部大家共同讨论最终敲定的一份代码规范,也可以使用网上呼声比较高的代码规范,规范的内容其实都是大同小异,这件事的重点在于“遵守”,这个需要所有开发者共同去维护。
但是每个人的代码习惯肯定是有差异的,如果想要把新的代码规范实施的比较彻底,这里给大家分享一个自动化的方案.
引子
大多数的时候,我们进入公司都是继续维护已经上线的成熟项目,所以项目也有了一定的代码量,如果此时才开始做代码规范,肯定还是基于后续新需求的新代码去做,如果有不太紧张的开发周期,再去做老代码的改造。
代码规范如何制作,这里就不赘述了,因为各个公司不可能完全相同,都需要根据各公司项目自身的特点去制作自己的规范。规范有了之后,实施可能多多少少都会遇到一些问题,由于多年的代码习惯,每个人都不是那么容易能保证每行代码都按照代码规范来写,提交代码的时候,review代码的人,一行行去review代码规范,也需要耗费很多的精力,明显不应该是个程序员该有的做事风格。
所以我们就要想想怎么可以提高代码规范的执行效率。
下面分享两种实现比较简单,而且很高效的方式:
- CodeSnippets
- Xcode类模板
CodeSnippets
CodeSnippets(代码片段),可以在Xcode中手动添加,选中任意一行代码,右键---Create Code Snippet
创建代码片段大家应该都用过这个功能,还是很方便的,创建之后,使用的时候类似于使用快捷键,一键代入编辑好的代码片段
参数解释
Title:名称(代码段名称)。
Summary:描述(代码段干啥用的)。
Platform:作用平台(All、iOS、macOS、tvOS、watchOS),选All就行。
Language:作用语言,如Objective-C。
Completion Shortcut:代码片段的快捷方式(例如你敲出for的时候会出来for循环的代码段)。
Completion Scopes:作用区域(例如拓展接口里面、方法里里面等等),没啥特殊要求选All就行。
空白区域:可编辑的代码片段。
自动化
有了CodeSnippets这个工具,相信你已经知道了怎么利用它来提高我们代码规范的效率了。那就是把所有的规范,都做成CodeSnippets,添加在自己电脑的Xcode上,这样就可以把大部分的规范交给CodeSnippets去做了,即提高了开发的效率,也提高了代码规范的效率。
我们自己创建的CodeSnippets保存在~/Library/Developer/Xcode/UserData
这个路径下,当你换电脑的时候,可以去这个路径下把CodeSnippets都备份一份,到新电脑里恢复到这个路径下,就可以使用了,非常的方便。
所以创建CodeSnippets的操作我们只需要做一次,然后把CodeSnippets导出来放到云端,这样所有使用者可以自己去下载和安装。文章最后我会放一份写好的CodeSnippets供大家下载参考和使用。
CodeSnippets 片段介绍
属性 片段
1.my_assign (assign 属性)
@property (nonatomic, assign) <#type#> <#name#>;
复制代码
- my_copy (copy 属性)
@property (nonatomic, copy) <#type#> *<#name#>;
复制代码
3.my_strong (strong 属性)
@property (nonatomic, strong) <#type#> *<#name#>;
复制代码
4.my_weak (weak 属性)
@property (nonatomic, weak) <#type#> *<#name#>;
复制代码
方法 片段
1.my_createCollectionView (创建collectionView 方法集合)
// 将其移动到interface中
@property (nonatomic, strong) UICollectionView *collectionView;
@property (nonatomic, strong) UICollectionViewFlowLayout *flowLayout;
#pragma mark - UICollectionView DataSource and Delegate
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return <#numbers#>;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
<#collectionViewcell#> *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identify forIndexPath:indexPath];
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
}
- (UICollectionViewFlowLayout *)flowLayout{
if (!_flowLayout) {
_flowLayout = [[UICollectionViewFlowLayout alloc]init];
_flowLayout.scrollDirection = UICollectionViewScrollDirectionVertical;
_flowLayout.itemSize = CGSizeMake(<#width#>,<#height#>);
_flowLayout.minimumInteritemSpacing = <#CGFloat#>;
_flowLayout.minimumLineSpacing = <#CGFloat#>;
}
return _flowLayout;
}
static NSString *const identify = @"collectionViewCell";
- (UICollectionView *)collectionView {
if (!_collectionView) {
_collectionView = [[UICollectionView alloc] init];
_collectionView = [[UICollectionView alloc] initWithFrame:<#frame#> collectionViewLayout:self.flowLayout];
_collectionView.backgroundColor = [UIColor whiteColor];
[_collectionView registerClass:[<#collectionViewcell#> class] forCellWithReuseIdentifier:identify];
_collectionView.dataSource = self;
_collectionView.delegate = self;
}
return _collectionView;
}
复制代码
2.my_createTableView (创建tableview 方法集合)
// 将其移动到interface中
@property (nonatomic, strong) UITableView *tableView;
#pragma mark - UITableViewDataSource
//设置Sections的个数
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return <#NSInteger number#>;
}
//设置row的个数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return <#NSInteger number#>;
}
//设置cell的内容
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *Identifier = <#NSString identifier#>;
<#UITableViewCell cell#> *cell = [tableView dequeueReusableCellWithIdentifier:Identifier];
if (cell==nil) {
cell = [[<#UITableViewCell cell#> alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:Identifier];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}
return cell;
}
#pragma mark - UITableViewDelegate
//设置cell的高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return <#CGFloat height#>;
}
//设置Sections的高度
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return <#CGFloat height#>;
}
//cell的点击事件
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
}
- (UITableView *)tableView {
if (!_tableView) {
_tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.backgroundColor = [UIColor clearColor];
//cell分割线的风格
[_tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
}
return _tableView;
}
复制代码
3.my_funsIns (实例方法)
- (<#return#>)<#funcName#> {
<#doSomeThing#>
}
复制代码
4.my_diffentStr (属性字符串方法)
- (NSMutableAttributedString *)setAttrStr:(NSString *)str subText:(NSString*)subText {
NSString *string = [NSString stringWithFormat:@"%@", str];
NSRange range = [string rangeOfString:subText];
NSMutableAttributedString *aString = [[NSMutableAttributedString alloc] initWithString:string];
[aString setAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:FONT_SIZE_14], NSForegroundColorAttributeName:UIColorFromRGB(0xdbac6f)}
range:range];
return astring;
}
复制代码
5.my_getBtn (button的get方法)
- (UIButton *)<#UIButton#> {
if (!_<#UIButton#>) {
_<#UIButton#> = [UIButton buttonWithType:UIButtonTypeCustom];
[_<#UIButton#> setImage:[UIImage imageNamed:@""] forState:UIControlStateNormal];
[_<#UIButton#> addTarget:self action:@selector(<#UIButton#>Fun) forControlEvents:UIControlEventTouchDown];
}
return _<#UIButton#>;
}
复制代码
6.my_getImageView (mageView的get方法)
- (UIImageView *)<#UIImageView#> {
if (!_<#UIImageView#>) {
_<#UIImageView#> = [[UIImageView alloc] init];
}
return _<#UIImageView#>;
}
复制代码
7.my_getLabel (label的get方法)
- (UILabel *)<#UILabel#> {
if (!_<#UILabel#>) {
_<#UILabel#> = [[UILabel alloc] init];
_<#UILabel#>.textColor = ;
_<#UILabel#>.font = ;
}
return _<#UILabel#>;
}
复制代码
8.my_getView (view的get方法)
- (UIView *)<#UIView view#> {
if (!_<#UIView view#>) {
_<#UIView view#> = [[UIView alloc] init];
}
return _<#UIView view#>;
}
复制代码
9.my_getCustomClass (自定义类型的get方法)
- (<#class#> *)<#class#> {
if (!_<#class#>) {
_<#class#> = [[<#class#> alloc] init];
}
return _<#class#>;
}
复制代码
方法内的代码 片段
1.my_shadow (view的阴影)
<#view#>.layer.shadowColor = <#color#>.CGColor;
<#view#>.layer.shadowRadius = 3;
<#view#>.layer.shadowOffset = CGSizeMake(0, 2);
<#view#>.layer.shadowOpacity = 0.1;
复制代码
2.my_shadowStr(设置带有阴影的字体)
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:<#title#>];
//设置字体
UIFont *baseFont = [UIFont systemFontOfSize:<#(CGFloat)#>];
[attrString addAttribute:NSFontAttributeName value:baseFont range:NSMakeRange(0, [<#title#> length])];//设置所有的字体
// 设置颜色
[attrString addAttribute:NSForegroundColorAttributeName value:<#color#> range:NSMakeRange(0, [<#title#> length])];
NSShadow *shadow = [[NSShadow alloc] init];
shadow.shadowColor = <#shadowColor#>;
shadow.shadowOffset = CGSizeMake(0, 2);
shadow.shadowBlurRadius = 5;
[attrString addAttribute:NSShadowAttributeName value:shadow range:NSMakeRange(0, [<#title#> length])];
复制代码
3.my_weakSelf (block 的 weiself )
__weak typeof(self) weakSelf = self;
复制代码
类模板
类模板这个名词可能不是那么熟悉,也是个开发中天天都要用到的东西,只是之前我们都用的系统的,现在可以尝试自定义一个模板了。
上面的每一项都是一个模板,是系统为我们定义的模板,比如第一项Source对应的模板代码都放在/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates/File\ Templates/iOS/Source
这个路径下。
自定义模板呢,也不难,新建一个文件夹,到Source下把所有的文件都copy一份,然后按照自己的代码规范去修改,这里规范,就是对于创建一个新类的规范了。比如创建一个继承自NSObject的类,.h文件中模板里自动添加了如下的内容:
#import <Foundation/Foundation.h>
#pragma mark - @class
#pragma mark - 常量
#pragma mark - 枚举
NS_ASSUME_NONNULL_BEGIN
/**
* <#类注释,说明类的功能#>
* @note <#额外说明的注意项,说明一些需要注意的地方,没有可取消此项。#>
*/
@interface TestNSObject : NSObject
@end
NS_ASSUME_NONNULL_END
复制代码
再比如创建一个继承自UIViewController的类,我们可以提前自定义的东西其实还挺多,把代码规范中的很多规则都可以直接写进去,增加代码可读性,也节省了很多编写重复代码的时间。
#import "TestViewController.h"
#pragma mark - @class
#pragma mark - 常量
#pragma mark - 枚举
@interface TestViewController ()
#pragma mark - 私有属性
@end
@implementation TestViewController
#pragma mark - Life cycle
- (void)viewDidLoad {
[super viewDidLoad];
[self configureNavigationbar];
[self createSubViews];
[self createSubViewsConstraints];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)dealloc {
NSLog(@"%@ - dealloc", NSStringFromClass([self class]));
}
#pragma mark - Events
#pragma mark - UITextFieldDelegate
#pragma mark - UITableViewDataSource
#pragma mark - UITableViewDelegate
#pragma mark - UIOtherComponentDelegate
#pragma mark - Custom Delegates
#pragma mark - Public Methods
#pragma mark - Private Methods
// 配置导航栏
- (void)configureNavigationbar {
self.title = <#标题#>;
}
// 添加子视图
- (void)createSubViews {
}
// 添加约束
- (void)createSubViewsConstraints {
}
#pragma mark - Getters and Setters
@end
复制代码
传送门
希望上面分享的这些代码规范的自动化方案,对你有帮助,我已经全部上传到git,方便取用。 使用方法也很简单:
脚本安装
-
下载 Template_CodeSnippets.zip
-
打开终端,cd 到 CodeSnippetsAndXcodeTemplates 文件夹下
-
在终端输入
./CodeSnippetsInstall.sh
运行脚本安装CodeSnippets -
输入
./ClassTemplateInstall.sh
运行脚本安装Class template,根据提示输入开机密码 即可。 -
Class template使用:重启Xcode,新建文件时选择MY Cocoa Touch Calss(如下图)。
6. CodeSnippets使用 : 在需要输入 代码片段的地方 输入快捷词即可(如下图)。
类模板手动安装及使用方法:
-
打开前往文件夹 复制粘贴路径:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates/File Templates/Source
-
将 MY Cocoa Touch Class.xctemplate 文件 拖入到当前文件夹里。
-
重启Xcode,新建文件时选择
CodeSnippets 手动安装及使用方法:
- 打开前往文件夹 复制粘贴路径:
~/Library/Developer/Xcode/UserData/CodeSnippets
- 如果前往失败,前往至:
~/Library/Developer/Xcode/UserData
中。 - 将 CodeSnippets文件里面的内容拖入到当前文件夹里。
- 如果没有CodeSnippets文件夹,直接将解压后的文件夹 放入到UserData中。
- 在需要输入 代码片段的地方 输入快捷词即可。