Creating your own file template in Xcode

Photo by Lala Azizli / Unsplash

A couple of years back I was working on a project structured with the MVVM pattern. We chose to structure our view models "Kickstarter style" with separate protocols for "Inputs" and "Outputs".

In general, all view models would share the same file structure:

protocol ExampleViewModelInputs {
    // properties and functions for input
}

protocol ExampleViewModelOutputs {
    // properties and functions for output
}

protocol ExampleViewModelType {
    var inputs: ExampleViewModelInputs { get }
    var outputs: ExampleViewModelOutputs { get }
}

final class ExampleViewModel: ExampleViewModelInputs, ExampleViewModelOutputs {
    // view model code
}

extension ExampleViewModel: ExampleViewModelType {
    var inputs: ExampleViewModelInputs { return self }
    var outputs: ExampleViewModelOutputs { return self }
}
Example View Model

Now, writing all this boilerplate code is tedious and boring. Fortunately, Xcode can help us with generating files with proper structure!

Go to Finder and navigate to /Applications/Xcode.app/Contents/Developer/Library/Xcode/Templates/File Templates/MultiPlatform/Source. This folder contains all Xcode source file templates. We are interested in Swift File.xctemplate. Make a copy of this template and name it View Model.xctemplate.

Inside View Model.xctemplate you will find two files

  • ___FILEBASENAME___.swift - this is the actual file that will be created. Its name will be replaced with the name we enter in the Xcode window
  • TemplateInfo.plist - metadata file, we can set all kinds of properties there, like name, description, and other advanced options

Open ___FILEBASENAME___.swift, it should look like this:

//___FILEHEADER___

import Foundation

This is our base ___FILEHEADER___ will be replaced with standard copyright notice Xcode adds to all source files. We are ready to create our own "implementation!"

We have to add our boilerplate code and replace some parts with wildcards Xcode will replace for us.

//___FILEHEADER___

import Foundation

protocol ___FILEBASENAME___Inputs {
    // properties and functions for input
}

protocol ___FILEBASENAME___Outputs {
    // properties and functions for output
}

protocol ___FILEBASENAME___Type {
    var inputs: ___FILEBASENAME___Inputs { get }
    var outputs: ___FILEBASENAME___Outputs { get }
}

final class ___FILEBASENAME___: ___FILEBASENAME___Inputs, ___FILEBASENAME___Outputs {
    // view model code
}

extension ___FILEBASENAME___: ___FILEBASENAME___Type {
    var inputs: ___FILEBASENAME___Inputs { return self }
    var outputs: ___FILEBASENAME___Outputs { return self }
}

I know it doesn't look good:) When we will use it in Xcode, the tool will replace all wildcards with the name entered in the file creation window. No more copy-pasting and changing names, the tool will make it for us!

We should edit TemplateInfo.plist to inform any potential developer what they can expect from this template:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>SupportsSwiftPackage</key>
	<true/>
	<key>Kind</key>
	<string>Xcode.IDEFoundation.TextSubstitutionFileTemplateKind</string>
	<key>Description</key>
	<string>An empty kickstarter style view model file. Please use view model class name as file name to ensure nice naming, ex: ExampleViewModel</string>
	<key>Summary</key>
	<string>View model template</string>
	<key>SortOrder</key>
	<string>1</string>
	<key>Image</key>
	<dict>
		<key>FileTypeIcon</key>
		<string>swift</string>
	</dict>
	<key>AllowedTypes</key>
	<array>
		<string>public.swift-source</string>
	</array>
    <key>Platforms</key>
    <array />
	<key>DefaultCompletionName</key>
	<string>File</string>
	<key>MainTemplateFile</key>
	<string>___FILEBASENAME___.swift</string>
</dict>
</plist>

Close and open Xcode, open any project and select File -> New -> File..., you should have the new template available:

New template in Xcode

Xcode templates are very powerful and can make your life easier. If your project is based on VIPER, the template can help create a view, presenter, interactor, router, and entity files automatically, which saves time and makes life this much happier and easier :)

Bonus

You can share templates with project mates, just commit a file somewhere in the repository and create a build script in the project that will copy the file to the Xcode folder. This way all team members will have always updated templates ready to use :)

Artur Gruchała

Artur Gruchała

I started learning iOS development when Swift was introduced. Since then I've tried Xamarin, Flutter, and React Native. Nothing is better than native code:)
Poland