Custom Xcode Template for Static Library in iOS

If you used Xcode then its certain that you come across and used templates for your projects. These can be file or project type templates such a Cocoa Touch Class, Storyboard, Core Data, Dynamic or Static Libraries. These are default templates which are bundled up with Xcode and for most of our use cases these should be sufficient, however if you are having to duplicate a certain functionality many times then things can get repetitive and inefficient. Lets say you have a policy of running a certain build script (SwiftLint for example) for all your project frameworks, you then have to introduce that script every time you introduce a new framework to your project. Soon this can get tedious especially when you have to introduce other functionalities such as Build Configurations.

Fortunately this process can be made easier by introducing Custom Templates. In this article i hope to example how one can create a custom Static Library template with pre-baked linting and custom configurations. This tutorial can also be used to create other project types such as dynamic libraries.

Where to store your templates?

Lets create some more folders…

The template folders are suffixed with .xctemplate, so lets create a folder called StaticFramework.xctemplate. Your .xctemplate folder contains all the required files to support your custom templates, with the most important file being the TemplateInfo.plist.

TemplateInfo.plist is where you define your template properties and settings such as the template types, build script, build configurations, nodes etc. These are unfortunately a fraction of the properties you can adopt but don’t be overwhelmed because you can copy the Xcode’s default templates and tweak the relevant information to create your custom templates. This will save you time having to write boilerplate template code for your custom templates.

Before we dive in to see how to utilise the default templates, lets cover some important properties in the TemplateInfo.plist file.

  1. Kind: A string type used to identify the template type for example you use Xcode.Xcode3.ProjectTemplateUnitKind for project templates and use Xcode.IDEFoundation.TextSubstitutionFileTemplateKind file templates.
  2. Identifier: A unique identifier for a template. Used to uniquely identify a template or to inherit properties from ancestry templates more on that later.
  3. Concrete: A Bool type. Must be set to YES for Xcode to show your template when choosing a template for your project. If missing or set to NO Xcode treats the template as an abstract base template that other templates can inherit from.
  4. Ancestors: An Array type to hold a collection on Identifier, used to inherit from other templates.

Copying the default static template

Navigate to the Project Templates/iOS/Framework & Library from the above path and copy the content of Cocoa Touch Static Library.xctemplate folder to your StaticFramework.xctemplate folder. Now you might be wondering what some of the files mean, lets take a look.

  1. ___PACKAGENAMEASIDENTIFIER___: The Objc and Swift files are default files you get when you create a project based on the selected language. For a Swift static lib you obtain the ___PACKAGENAMEASIDENTIFIER___.swift and for Objc you obtain the .h and .m files. Macros are used as file names so they are replaced on project creation. For more info on what macro to use visit here.
  2. TemplateIcon.png: These are optional png files used to spice up your custom templates, so that its more recognisable.

Setting an identifier

Setting up swiftlint

<dict>
<key>Class</key>
<string>ShellScript</string>
<key>Name</key>
<string>Run SwiftLint</string>
<key>ShellPath</key>
<string>/bin/sh</string>
<key>ShellScript</key>
<string>$(git rev-parse --show-toplevel)/Tools/SwiftLint/swiftlint --path ${SRCROOT}</string
</dict>

The above ShellScript will perform Linting on all files in the root of your static lib, off course the above script will only work if the static lib was added to your project which contains the swiftlint executable under /Tools/SwiftLint. But remember to introduce the appropriate changes (if any) according to your swiftlint setup.

Setting up Build Configuration

<key>Project</key>
<dict>
<key>Configurations</key>
<dict>
<key>Debug</key>
<dict/>
<key>Stage</key>
<dict/>
<key>AppStore</key>
<dict/>
</dict>
</dict>

The above setup will add 3 configurations to our static lib, Debug, Stage and AppStore.

Now that we finished adding all the appropriate properties to our TemplateInfo.plist we can now test it by creating a new Static library using our custom template by going to File -> New -> Project. When you do that you should see something like this (you may have a different icon😎):

It is important to note that if the Concrete property was set to NO in our TemplateInfo.plist then we would not see our custom template, Xcode treats the template as an abstract base template that other templates can inherit from. You may have noticed that the template shown above is grouped under the name Personal Static Libraries because the .xctemplate folder inside is hosting a non Concrete type template.

If you have any issues with your setup please comment below and i will try my best to help out 😊. Also check out my repo on Project templates where i am using inheritance to create custom templates for dynamic and static libs so that build configurations and build scripts are not copied but reused.

A Software Engineer with a passion for technology. Working as an iOS Developer @BBC