日常开发中,我们每次新增一个模块时,在创建模块各部分文件的操作上总是重复的,创建View,Model,ViewModel,VC,还要设定相关参数。这类操作可以用 Xcode 的模板来简化。
【模板?为什么要自定义模板?】
在开发中,模板是将一个事物的结构规律予以固定化、标准化的成果,它体现的是结构形式的标准化。就像我们自定义的“快捷代码”,它也是模板。本文主要介绍 Xcode 中创建模块时使用的模板(Templates)。
开发中每天与模板相伴,上图是 Xcode 提供的系统模板,这些模板帮助我们更快的创建对应的模块,以 ViewController 为例:
在创建面板上只需要设定好”名称“、”基类“、”是否要生成对应的XIB文件“,系统就会自动为我们创建好这些文件,命名好相关的类,关联好 XIB 与 ViewController 。模板将自动完成这些,如果我们单独进行操作,将会一次又一次为此消耗掉不少时间。
系统提供的模板都是最最基础的,在日常开发中,项目模块的架构都会有一定规律可循,无论是什么结构(MVC/MVVM/MVP),都可以通过 Xcode 的自定义模板来避免重复创建Model、ViewModel、View(甚至更多)的情况发生。
【系统的模板】
开始创建自定义模板之前,先了解下系统的模板是什么样的。系统模板路径为:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates
可以看到这里分为”文件模板“和”项目模板“,项目模板是我们创建项目时使用的(如 Single View App、各种 Extension 等等),这里不讨论。我们主要看文件模板,文件模板中种类繁多,这里主要看 “Cocoa Touch Class.xctemplate”,完整路径为:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates/File Templates/Source/Cocoa Touch Class.xctemplate
这个是CocoaTouch相关的模板,例如上面提到的 ViewController 。
模板文件
以 UIViewControllerXIBSwift 为例,当语言为Swift,基类为 UIViewController,并勾选了生成XIB时,Xcode就会根据此模板生成对应的文件。可以看到模板中有两个文件:
Xcode会根据这两个文件为模板生成我们的 ViewController 及关联的 XIB 文件。
可以看到,两个文件名都为 __FILEBASENAME__
,这里就要提到模板中的宏,宏在Xcode创建模板时会被替换成对应的值(无论是文件名,还是文件内部),此处的 __FILEBASENAME__
在创建模板后会被替换成设置的文件名。更多的宏可查阅官方文档
模块配置文件 TemplateInfo.plist
系统模板中这些配置字段的含义如下:
-
Kind: 模板类型
此处固定为 Xcode.IDEFoundation.TextSubstitutionFileTemplateKind,还有 CoreData 相关的Xcode.IDECoreDataModeler.ManagedObjectTemplateKind,本文不做介绍
-
Description: 描述文字
Xcode早期版本创建模板时可以看到描述文字,现在的版本默认不显示(有说创建时双击可显示,老夫双击烂了也没反应)
-
Summary: 简要文字
与 Description 一样,是对模板的介绍文字。
-
SortOrder: 排序优先级
在模板面板中排序的优先级
-
DefaultCompletionName: 默认文件名
默认文件名是在保存文件对话框中文件的默认名称
-
Platforms: 模板所支持的环境
模板会出现在包含的环境所对应导航栏下,相关环境字段如下:
com.apple.platform.macosx
com.apple.platform.iphoneos
com.apple.platform.watchos
com.apple.platform.appletvos
-
Options: 模板选项
Options 是一个集合,配置创建模板的面板相关属性,如名称,类型,选项卡,选项约束等。模板中的宏会被此处的配置值替换
Options 中有四个配置选项,通过 Name 等描述字段可知分别是“类名”、“基类名”、“是否创建XIB”、“语言选取”。
常见字段介绍:
identifier:
模板选项的唯一标识,我们在模板文件中可以通过宏来引用它的值。
也就是说它也用来保存模板选项的值。例如系统 Viewcontroller 模板文件中引用创建模板时开发者设定的基类名使用了:
___VARIABLE_cocoaTouchSubclass___
这里的___VARIABLE_XXXXXX___
也是宏,紧跟着的 cocoaTouchSubclass 是第二个 option 的 identifier 的值。
Type:
选项类型。ViewController 中类型为text(手动输入),基类为class(类选取)创建XIB为checkbox(勾选框),语言选取为popup(弹框)。
Values:
某类值的集合。这个值跟当前选项具体内容有关,最直观的就是语言选项中的Values就是用户可以选择的两种开发语言Objective-C与Swift。
Default:
选项默认值。这个跟选项类型有关,例如 checkbox 类型的创建XIB选项默认创建,其值就为false,语言选择是必选的,其默认值就为Objective-C。
RequiredOptions:
必要选项,字面是这个意思,从XIB选项中可以看出,这个字段是与checkbox 配合的,当基类出现指定的值时,勾选框就可选。
 
很多字段没有一一列出,可以自行尝试修改去理解其含义和使用方法,不过最好还是不要更改系统模板,可以将系统模板复制一份或者拷贝一份到我们自定义的模板中。
自定义模板的路径为:
/Library/Developer/Xcode/Templates/File Template/Custom/
默认情况下是没有 Templates 文件的,自己创建就好,将系统模板(Cocoa Touch Class.xctemplate)整个拷贝到这里,最好自己改个名字方便理解(如:SysCopy.xctemplate)。
拷贝过来后,在Xcode中创建模板时就会看到多了一个 "Custom" 栏,里面正好是拷贝并重命名后的系统模板:
现在就可以任意凌虐这份拷贝后的模板了。
【小结】:
由上可以看出 Xcode 的模板文件根据其配置文件与开发者交互来定制化输出对应的文件。
【自定义模板】
以 MVC/MVVM 为例,每个模块都需要重复配置 View,Model,ViewController,XIB等文件,现在尝试通过自定义模板来简化重复的操作,每次只需要输入模块名称即可。
1.创建模板
1)在/Library/Developer/Xcode/Templates/File Template/Custom/
路径下创建模板文件 RJMVVM.xctemplate
2)在 RJMVVM 模板文件中创建配置文件 TemplateInfo.plist
,为了方便建议直接拷贝系统配置文件。
为了精简,本文示例只留下了必要字段与一个模块名输入框。
效果如下:
此时创建模块就可以在 Xcode 模板创建面板中看到 RJMVVM 选项,不过现在创建后没有任何反应。
2.创建文件
在 RJMVVM.xctemplate 模板文件内创建 ViewController 的模板。以 ViewController 文件为例:
// MyVC.swift
import UIKit
class MyVC: MyBaseVC {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
// 各种业务
extension MyVC {
}
现在再创建模块的话,Xcode 会将 MyVC.Swift直接复制到项目中。同样的,我们可以将View,Model,ViewModel 等需要制作成模板的文件也添加到模板文件中。
3.利用宏关联文件
在第二步中,模板只是简单地将相关文件拷贝到了项目中,输入的模块名想要关联到文件名、类名等需要用到系统所提供的宏。上面提到的“___VARIABLE_XXXXXXX___”
就是一种宏,用来获取配置文件中的值。要获取模块的名称需要用到的是"___FILEBASENAME___"
。
这里要特别注意的是,
__FILEBASENAME__
是options
中的productName
选项派生的,所以,要使用这个宏,就不能更改productName
,否则宏无法关联到我们输入的名称,其默认将会使用 DefaultCompletionName 字段的值。
不仅仅是文件名,还有代码中的类名,基类名,协议等都可以进行关联,此处以类名为例(毕竟本例只有一个输入框),我们直接用文件名的命名方法来修改相关类的名称,不过此处用到的宏是___FILEBASENAMEASIDENTIFIER___
,以 ViewController 模板为例进行修改
// VC
// 此处的 ___FILEBASENAMEASIDENTIFIER___ 与文件名相同
class ___FILEBASENAMEASIDENTIFIER___: MyBaseVC {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
extension ___FILEBASENAMEASIDENTIFIER___ {
}
此时再去创建模板的话,ViewController 的文件就会根据输入的名称去修改替换模板文件名称中的宏及其代码中的宏。
至此,一个最最简单的模板就完成了,不用每次创建新模块都要花几分钟来配置文件结构。
【 Do you want know more ? 】
如何关联 XIB 文件?
与一般文件相同,将XIB文件放入模板文件中,并利用宏配置其名称,创建模板时将自动创建相关的XIB文件。这里要注意的是,XIB 文件基本都是与 VC 进行绑定的。我们直接将系统模板的XIB文件打开看看:
注意图中红框部分,xib的类这里用到了宏,也就是说模板会将XIB跟宏所代表的类关联起来。
照猫画虎,将这段文本复制过去即可。若文件和类名有什么其他命名规则,只需要更新这个宏就可以了,例如本文示例的 ViewController 类后面都有 VC,而 XIB 没有,所以此处的宏需要跟上VC才能跟VC的类关联起来:___FILEBASENAMEASIDENTIFIER___VC
。
如何关联配置中的自定义名称?
由系统模板的基类绑定可知,通过宏可以拿到配置文件中的值。添加一个 Identifier
为 testString
的 text
类型 option
:
我们在模板文件中加入这个宏进行测试:
// 配置文件中的testString为:(___VARIABLE_testString___)
创建模块后相关宏将被输入值所替换:
还有哪些宏?
更多宏可查看官方文档在此
需要注意的是:
宏的前后各有三个下划线
宏的前后各有三个下划线
宏的前后各有三个下划线
如何将模块包含在文件夹中一并创建?
可以是可以···但目前创建出来的是文件(蓝色),而不是 Xcode 的 group文件(黄色),多方查阅资料后,项目模板是可以的,但文件模板不行(202007)。目前只能手动创建 group文件(黄色)。
如何让模块骚气一点(图标)?
模板可以自定义图标,系统模板提供了一倍图和二倍图,名称为 TemplateIcon,自定义图标只需在自定义模块文件下添加相同名称图片就可以了,效果如下:
Tips:
系统图标的大小为48x48(二倍图为96x96),大小不同也可以。
总结
Xcode 模板借助配置文件与宏对模板文件进行定制。
不同的项目,规范不同,模板也就会有差异,开发者需根据项目具体规范,制定合适的模板才能事半功倍。
感谢阅读