0%

自定义Xcode模板

很多时候我们需要一个较复杂场景的Demo工程来验证点东西或者研究某个技术,直接在公司项目工程中实验运行又太慢,并且还可能受到其他代码的影响。而Xcode自身提供的工程模板又太过简单,导致每次都要浪费很多时间编写重复的代码来搭建环境。为了提高效率,我们可以自定义工程模板和文件模板。

如下图,系统提供的默认模板其实都在Xcode.app中,自定义工程模板和文件模板最好的办法就是参考系统的模板。

系统的工程模板位置:

1
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates/Project Templates/iOS

系统的文件模板位置:

1
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates/File Templates

以上是系统默认的模板存储路径,对于自定义的模板则需要存放在其他路径:

自定义工程模板的路径需要存放在:~/Library/Developer/Xcode/Templates/Project Templates/Application/.

自定义文件模板的路径需要存放在:~/Library/Developer/Xcode/Templates/File Templates/.

当做好自己的模板后只需要存放在上述位置,重启Xcode就能看到我们自己的工程模板了。

注:如果上述路径不存在则需要自己创建好。

了解系统的工程模板

在制作自己的工程模板之前,先来了解一下系统的工程模板都有些啥,以最简单的Single View App模板为例:

每个模板文件夹中都会包含一个模板信息的plist文件里面是一些关于模板的配置。我们要做的也就是修改TemplateInfo.plist文件。

简单介绍一下TemplateInfo.plist文件:

Kind

分为工程模板和文件模板,这个不用修改使用默认的就好。

工程模板:Xcode.Xcode3.ProjectTemplateUnitKind

文件模板:Xcode.IDEFoundation.TextSubstitutionFileTemplateKind

Identifier

模板ID,用于唯一标识一个模板。类似于类名。

Ancestors

模板系统允许模板继承和重写其他模板,Ancestors里面包含的就是当前模板继承的其他模板的ID(就是上面那个Identifier)。

Single View App模板的Ancestors包含两个父模板:

com.apple.dt.unit.coreDataCocoaTouchApplication:如果你在创建工程时勾线了CoreData,这个模板就会让Xcode在AppDelegate中添加CoreData的样板文件。

com.apple.dt.unit.sceneLifecycleApplication:这个是iOS13出的,会让Xcode创建SceneDelegate.h/m。

上面两个模板又都继承自Cocoa Touch Application Base模板,

com.apple.dt.unit.cocoaTouchApplicationBase:这个模板主要是在AppDelegate中添加一些样板代码和Info.plist的一些设置。

允许模板的继承和重写就可以让各个模板功能清晰,代码复用,达到类似于类的继承的效果。

Concrete

必须设置为YES才能在Xcode面板中显示出来。

Description

模板的描述。

SortOrder

模板在Xcode面板中的显示位置。值越大显示在越后面。

Options

这个就是模板的主要内容了,里面包括要创建的类文件,存根方法的实现等。Nodes里定义了一些key,它的值就是Definitions里的东西。参照系统的写法我们就可以依葫芦画瓢制作自己的模板了。

制作自己的工程模板

接下来制作自己的工程模板,使用该模板创建的Demo工程将自动包含一个tabBar控制器,及三个子navigation控制器。其中的MATHomeViewController上添加了一个tableView,MATMessageViewController上添加了一个按钮。支持OC和Swift。

首先拷贝一份系统的Single View App模板,我们主要基于Single View App模板进行修改。

修改文件名为Demo App.xctemplate,文件夹下的模板图标可以换一下。接下来就是对TemplateInfo.plist文件的修改了。

Identifier

随便取个名称,com.apple.dt.unit.MATDemoApplication

Ancestors

由于不想要Storyboard,所以用com.apple.dt.unit.cocoaTouchApplicationBase替换掉com.apple.dt.unit.sceneLifecycleApplication模板。

SortOrder

取值100。让它排在系统的后面。

接下来就是大头Options。

Options

更改AppDelegate

在Nodes里添加一个item AppDelegate.m:imports:importHeader:MATTabBarController.h:表示在AppDelegate.m里面导入MATTabBarController.h头文件,这样Xcode在创建工程时就会自动在AppDelegate.m里添加#import"MATTabBarController.h"

在Nodes里添加一个item AppDelegate.m:implementation:methods:applicationdidFinishLaunchingWithOptions:body

并在Definitions里添加对应的值:

1
2
3
4
5
self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
self.window.backgroundColor = [UIColor whiteColor];
MATTabBarController *tabController = [[MATTabBarController alloc] init];
self.window.rootViewController = tabController;
[self.window makeKeyAndVisible];

这样Xcode就会自动在AppDelegate.m里didFinishLaunchingWithOptions方法里面添加上述代码。

如图:

Nodes:

Definitions:

添加已有的类文件

MATTabBarController.h/m是我们自己提供的类文件,为了让Xcode在创建工程时能够找到这些类,我们需要在模板文件中指明。

在Nodes里添加两个item:MATTabBarController.hMATTabBarController.m

并在Definitions里添加对应的值:

key:MATTabBarController.h,value类型选择字典。字典中添加key:Path,value为文件的路径。

动态创建类

这个参照系统的就可以了:

红色划线处替换为你自己的类名即可。

添加方法

让Xcode在创建的类中自动添加一个方法。

在Nodes里添加两个item:

MATMessageViewController.m:implementation:methods:btnDidClicked(- (void\)btnDidClicked:(UIButton *\)sender)

MATMessageViewController.m:implementation:methods:btnDidClicked:body

即方法声明和方法实现。

在Definitions里添加MATMessageViewController.m:implementation:methods:btnDidClicked:body的值,这里就是btnDidClicked方法的实现:

1
NSLog(@"btnDidClicked");

添加属性及懒加载实现

让Xcode在创建的类中自动添加一个属性及属性的懒加载实现。

在Nodes里添加三个item

MATMessageViewController.m:extension:btn

MATMessageViewController.m:implementation:methods:btn(- (UIButton *\)btn)

MATMessageViewController.m:implementation:methods:btn:return

在Definitions添加对应的值:

MATMessageViewController.m:extension:btn的值:

@property (strong, nonatomic) UIButton *btn;

MATMessageViewController.m:implementation:methods:btn:return的值:

1
2
3
4
5
6
7
8
9
if (_btn == nil) {
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(0, 0, 100, 44);
btn.backgroundColor = [UIColor redColor];
[btn setTitle:@"button" forState:UIControlStateNormal];
[btn addTarget:self action:@selector(btnDidClicked:) forControlEvents:UIControlEventTouchUpInside];
_btn = btn;
}
return _btn;

到此为止工程模板就差不多了,将其拷贝到~/Library/Developer/Xcode/Templates/Project Templates/Application/目录下,重启Xcode就可以看到我们自己的模板了。

制作自己的文件模板

制作文件模板最好也是参照系统的文件模板。

新建一个文件夹命名为ZACustom,然后从目录:

/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates/File Templates/Source

拷贝一份Cocoa Touch Class.xctemplate,到该目录下。

一般新建UIViewController和NSObject较多,所以可以只保留这两个类,其他的类文件夹可以删掉。

文件模板的TemplateInfo.plist文件基本不需要修改,只需要修改各类文件夹下的___FILEBASENAME___.m文件。

修改UIViewControllerObjective-C文件夹下的___FILEBASENAME___.m,新增代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
//___FILEHEADER___

#import "___FILEBASENAME___.h"

@interface ___FILEBASENAMEASIDENTIFIER___ ()

@end

@implementation ___FILEBASENAMEASIDENTIFIER___

// MARK: life cycle

- (void)viewDidLoad {
[super viewDidLoad];

}

- (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];

}


// MARK: system protocol




// MARK: custom protocol




// MARK: notification




// MARK: event response




// MARK: public method




// MARK: private method




// MARK: setter & getter




@end

这样创建的UIViewController子类就自带这些注释和实现的方法。

可以修改NSObjectObjective-C文件夹下的___FILEBASENAME___.h,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//___FILEHEADER___

___IMPORTHEADER_cocoaTouchSubclass___

NS_ASSUME_NONNULL_BEGIN

@interface ___FILEBASENAMEASIDENTIFIER___ : ___VARIABLE_cocoaTouchSubclass___

@property(nonatomic, copy) NSString *<#property1#>;

@property(nonatomic, copy) NSString *<#property2#>;

@property(nonatomic, copy) NSString *<#property3#>;

@property(nonatomic, copy) NSString *<#property4#>;

@property(nonatomic, copy) NSString *<#property5#>;

@property(nonatomic, assign) NSInteger <#property6#>;

@property(nonatomic, assign) float <#property7#>;

@end

NS_ASSUME_NONNULL_END

这样创建的模型,自动就有7个占位属性了。

最后将文件夹ZACustom拷贝到~/Library/Developer/Xcode/Templates/File Templates/目录下,重启Xcode就可以看到我们自己定义的文件模板了。

有需要的朋友可以点击下方链接下载使用:

FireDemoAppTemplate

觉得文章有帮助可以打赏一下哦!