[Xcode] Boost Team Productivity with XCTemplate (FileTemplate)
Boosting Productivity in the DelightRoom iOS Group
Introduction
Recently, the iOS group adopted XCTemplate and CodeSnippet as part of our efforts to boost productivity. This has allowed us to reduce the overhead of repetitive, unnecessary tasks and dedicate more time and energy to code quality and architecture.
Why?
Why do we need code automation like XCTemplate and CodeSnippet? 🤔 I focused on the following problems:
Wasted effort on repetitive and unnecessary tasks
Poor readability caused by inconsistent code
These issues clearly had a direct impact on the entire team, and there was definitely room for a fix. Once the problems were clearly defined, our goals naturally followed.
We can reduce the cost of writing code through code automation.
We can improve readability by baking the conventions agreed upon within the group into that automation.
And since cost reduction was our biggest goal,
3. We can minimize adoption overhead through easy distribution.
With this as an additional goal, we got to work on XCTemplate and CodeSnippet. Today, I'd like to talk about XCTemplate.
What is XCTemplate?
For those who might be unfamiliar with XCTemplate, let's start by getting on the same page.
When creating a file, you've probably seen a screen like this pretty often.
We call each of these templates here an XCTemplate or FileTemplate. In fact, we've already been using XCTemplate!
So, taking comfort in the fact that we aren't building something completely foreign (and that we have existing templates to reference), let's move on to the next part.
Creating an XCTemplate Folder
XCTemplate is fundamentally folder-based. Just like in the image right above, it is structured by placing the necessary files inside a single .xctemplate folder.
And inside this folder, the following files are strictly required:
TemplateIcon.png
TemplateInfo.plist
___FILEBASENAME___.swift
TemplateIcon.png
As you might have guessed, this is the thumbnail image for the file template.
2. TemplateInfo.plist
This file contains the information necessary for the template to be generated.
3. ___FILEBASENAME___.swift
This is the final file that gets generated.
Now, let's look at an actual TemplateInfo.plist and dive a little deeper.
TemplateInfo.plist
Kind [Required]: Defines the type of the template.
File template: Xcode.IDEFoundation.TextSubstitutionFileTemplateKind
Project template : Xcode.Xcode3.ProjectTemplateUnitKind
SortOrder [Required]: Determines the order in which the template is displayed.
Platforms [Optional]: Defines which platforms it is used on.
ios : com.apple.platform.iphoneos
macosx: com.apple.platform.macosx
Item ‘n’: Each item stacked vertically.
Identifier: You can specify an ID to fetch this item from elsewhere.
Options [Optional]: You can specify various options for file generation.
Type: You can provide and specify multiple types of UI (text/checkbox/popup/combobox/static, etc.).
Required: Specifies it as a mandatory option.
NotPersisted: Specifies whether to remember this property for next time.
Once the Options are all set, let's briefly talk about the implementation part through an example of a UseCase we actually use: ___VARIABLE_productName___UseCase.swift.
___VARIABLE_productName___UseCase.swift
The UseCase conventions within the DelightRoom iOS team are as follows:
Name the interface: productName + UseCase.
Name the implementation: productName + UseCaseImpl.
The interface's API only has the execute function.
If parameters are needed, the engineer implements them directly.
To easily implement these rules, ___VARIABLE_productName___UseCase.swift can be structured like this:
Through __VARIABLE_identifier__, it fetches the productName you entered during file creation, and uses it to generate the file according to the agreed-upon rules.
We need to allow the UseCase to choose between two access modifiers: public and internal. We add a PublicAccess item to the TemplateInfo.plist and divide the folder accordingly.
Once this is done, we can easily generate UseCase files with a unified format.
Sharing and Distributing Within the Team
We borrowed the approach used in RIBs so we could easily share these customized XCTemplates with teammates.
ref: https://github.com/uber/RIBs/blob/main/ios/tooling/install-xcode-template.sh
# Configuration
XCODE_TEMPLATE_DIR=$HOME'/Library/Developer/Xcode/Templates/File Templates/Alarmy/iOS/Clean Swift'
# Copy 'Alarmy Clean Swift file' templates into the local 'Alarmy Clean Swift file' template directory
xcodeFileTemplate () {
echo "[Copying] Alarmy Clean Swift templates... to Xcode"
if [ -d "$XCODE_TEMPLATE_DIR" ]; then
rm -R "$XCODE_TEMPLATE_DIR"
fi
mkdir -p "$XCODE_TEMPLATE_DIR"
cp -R "File Templetes"/ "$XCODE_TEMPLATE_DIR"
echo "[success 🎉] copying File Templetes!"
}
xcodeFileTemplate
echo "Please restart Xcode 👨💻"By placing these templates and the .sh file right inside the project, we can continuously manage their versions as well.
Through this, we can easily turn our team's architectural design patterns into templates. If needed, we can even set it up to generate a View and ViewModel simultaneously.
Conclusion
Now we can generate code easier and faster, strictly following our agreed-upon conventions. And the time saved can be reinvested into solving more challenging problems. 😉
Thanks for reading this long post 👨💻
👉 Check out our Instagram for a sneak peek into daily life at DelightRoom