For quite a long time I wanted to experiment with the creation of a custom Xcode template and finally the time has come!! In this article, I will try to describe step-by-step the process of creating a custom Xcode template from scratch. For those unfamiliar with the term, Xcode template is something we use quite often. When creating a new file or a new project, Xcode offers a wide variety of template options to choose from.

For example, when creating a Cocoa Touch Class, you select the superclass and the preferred language, be it Swift or Objective-C. Based on these choices, a file (or more) will be created. In case of a UIViewController subclass, the end result will be a file with a subclass of UIVIewController containing the viewDidLoad implementation in the selected language. Though, apart from those predefined templates, we are also able to create and add our own custom Xcode templates, or use some custom templates developed by the community.

What is the end result?

In my case, what I would like to achieve is to create a template for when I add a new feature/module to an existing project. Depending on the architecture of the project and the team, each feature usually follows some specific conventions regarding the folder structure and the required components. That means that every time a new feature is added, we have to do some manual steps to create the folder structure and the classes. For this article, I am going to use Coordinators and MVVM, so every new feature adheres to the following folder and naming conventions

<MODULE_NAME>
├── Coordinators
│   └── <MODULE_NAME>Coordinator.swift
├── ViewControllers
│   └── <MODULE_NAME>ViewController.swift
└── ViewModels
    └── <MODULE_NAME>ViewModel.swift

And this is what I would like to achieve. An Xcode custom template that will create the above-mentioned structure and add all the boilerplate code for the instantiation of each component.

How do I start?

A way to start is by taking a look at the existing file templates. You can find all the default Xcode templates inside the directory:

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

Navigating through this directory, you can find a bunch of templates. For instance, the Cocoa Touch Class template is located under File Templates > Source > Cocoa Touch Class.xctemplate. There, you can find all the template files for all the possible options that you have when creating a Cocoa Touch Class from Xcode.

But, if you want to add your own custom template, this directory is not the proper one. Instead, use

~/Library/Developer/Xcode/Templates/

This folder contains two sub-folders: File Templates and Project Templates. The first one is for the templates that are meant to be used on an existing project, and is the location where we are going to place our template, whereas Project Templates is the location for templates used when creating an entirely new project.

So, now we are ready to start building our own template!!

Preparation

To start with, let’s create a folder inside this directory, that will eventually contain the template files. The folder should have an .xctemplate extension. For example, I use IDModule.xctemplate. For a template to be visible on Xcode it is required to have three files, the TemplateInfo.plist, TemplateIcon.png and TemplateIcon@2x.png.

The TemplateIcon.img is a 48x48 image whereas the TemplateIcon@2x.png is a 96x96 image and are the thumbnails that will be presented in the template selection window on Xcode.

The TemplateInfo.plist will contain the configuration of the template and for my case it will look like this (the actual file can be found on this gist).

Xcode custom template TemplateInfo.plist screenshot

As you can see, it contains three keys: Kind, Platforms and Options. Let’s check each of those one by one.

The first one is the Kind. It describes the “kind” of the template and here we use the value:

Xcode.IDEFoundation.TextSubstitutionFileTemplateKind

The next one is the Platforms key that describes which platform to target and it’s value is an array. Since our template is only for iOS, we only add one item with value com.apple.platform.iphoneos.

Lastly is the Options key which can be used to allow users to customize the template. In our scenario, we would like to get the name of the module from a user input. The value of this key is an array and each of the items is a dictionary with keys like Description, Identifier, Name, Required and Type. We use productName as an identifier so that Xcode will know that this is the name of the module and using it will populate some Xcode so-called text macros (___FILEBASENAME___ and ___FILEBASENAMEASIDENTIFIER___) that will later be used to create the directory and the files.

To find more information about the Xcode text macros, refer to the documentation provided by Apple and more specifically to Text macros reference and Text macro format.

Without further ado, we can now try to create a new template on Xcode and the module will be there but no file will be created yet.

Xcode ID Module screenshot screenshot

So let’s move on to creating the actual template!!

The template

As we mention before, there are some macros that can be used when creating a template. One of those is ___FILEBASENAME___, and it’s value is what we typed on the productName field when creating the module. To make our template create a folder with the name that we typed on the field, we will create a new folder inside the IDModule.xctemplate folder, and we will name it ___FILEBASENAME___ .

Next, we will create three more folders, named Coordinators, ViewControllers and ViewModels inside the ___FILEBASENAME___ folder. Finally, we will create three files named ___FILEBASENAME___Coordinator.swift, ___FILEBASENAME___ViewController.swift and ___FILEBASENAME___ViewModel.swift inside Coordinators, ViewControllers and ViewModels folders respectively.

The final structure of the IDModule.xctemplate folder will be something like this:

.
├── TemplateIcon.png
├── TemplateIcon@2x.png
├── TemplateInfo.plist
└── ___FILEBASENAME___
    ├── Coordinators
    │   └── ___FILEBASENAME___Coordinator.swift
    ├── ViewControllers
    │   └── ___FILEBASENAME___ViewController.swift
    └── ViewModels
        └── ___FILEBASENAME___ViewModel.swift

Until now, we have created the folder structure and the files. Let’s now move to the contents of each of those files.

For the files, we are going to use a few more text macros like ___FILEHEADER___, ___FILEBASENAMEASIDENTIFIER___ and ___VARIABLE_productName:identifier___ that will allow us to set the file header and the proper name for each class, struct and variable in the files.

___FILEBASENAME___Coordinator.swift
//___FILEHEADER___
import Foundation

class ___FILEBASENAMEASIDENTIFIER___ {

    func start() {

    }

    private lazy var viewModel: ___VARIABLE_productName:identifier___ViewModel = {
        let vm = ___VARIABLE_productName:identifier___ViewModel()
        return vm
    }()

    private lazy var viewController: ___VARIABLE_productName:identifier___ViewController = {
        let vc = ___VARIABLE_productName:identifier___ViewController(with: viewModel)
        return vc
    }()
}
___FILEBASENAME___ViewController.swift
//___FILEHEADER___
import UIKit

class ___FILEBASENAMEASIDENTIFIER___: UIViewController {

    init(with viewModel: ___VARIABLE_productName:identifier___ViewModel) {
        self.viewModel = viewModel
        super.init(nibName: nil, bundle: nil)
    }

    @available(*, unavailable)
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    private let viewModel: ___VARIABLE_productName:identifier___ViewModel
}
___FILEBASENAME___ViewModel.swift
//___FILEHEADER___
import Foundation

struct ___FILEBASENAMEASIDENTIFIER___{

}

One interesting thing to notice is that ___FILEBASENAMEASIDENTIFIER___ is re-evaluated based on the context. For example, inside the ___FILEBASENAME___Coordinator.swift the value of ___FILEBASENAME___ and ___FILEBASENAMEASIDENTIFIER___ will be the actual name of the file including the Coordinator suffix.

All these files and the TemplateInfo.plist are available on a gist.

So now it’s time to create a new module on Xcode!! Let’s say we want to add a new Login feature to a new app!! Using the IDModule template, the output that we will get will be like this: Xcode Template files screenshot

But!!

Some of you may have already noticed that something is wrong with the folder created. The color signals that it’s not a group and if you try to instantiate the Coordinator from somewhere in the rest of the app, you will be unable to do so.

This is happening because the template creates just a folder and not actually an Xcode group, so all the files inside the module are not members of the app target. Sadly, after some research, it seems that it is not currently possible to create a new group when you use a new file template, only when creating a template for a new project. A quick solution is to create the group from the folder and then delete the reference to the initial folder.

Point to the parent folder, right click and choose “Add files to “…””.

Xcode Add files to target screenshot

A new window will pop up. There, choose the root folder of your module, and pick “Create groups” for the field “Added folders”. Then press “Add”.

Xcode Select files screenshot

The new group is created, and now we can safely right click on the old folder of our module, choose “Delete” and pick the option “Remove reference”.

The new module is ready to be used!

Conclusion

To sum up, this article can be used as a guide to create a custom template and presents how easy and straight-forward is to do so. Of course it doesn’t cover all the available options such as adding more fields/options when creating a template and not only the name and based on them to create different file (like the case with Swift or Objective-C option) and maybe creating a base template that can be used by many child templates (the case for most of the Xcode predefined templates). In general, Xcode custom templates can be used to ease, in some extend, the process of creating a new file or a new module, eventually resulting in a more efficient way for working since it will remove some time-consuming and not so interesting tasks. And maybe guarantee some consistency amongst team members in the way modules and files are created.

Thanks for reading, I hope you find this post useful!

Feel free to follow me on Twitter and let me know what’s your opinion about Xcode templates and whether you are using them in your projects!