Customizing Xcode file header comments

For quite a long time creating a new source file in projects followed a similar routine: cmd + n, create a file, replace the generated header with the template from snippet or another file. I almost got used to it but still wondered if the default format could be somehow customized to get rid of all that manual work.

I have never been tied to using a default Xcode-generated header being like

//
//  File.swift
//  MyCoolProject
//
//  Created by Matrejek, Mateusz on 25/04/2020.
//  Copyright © 2020 MyAwesomeCompany Inc. All rights reserved.
//

I found it too verbose and in fact I didn't rarely need all that information, especially for personal or hobby stuff. Also, the majority of the projects I worked on used something more similar to the format below

//
// Copyright (c) 2019 and Confidential to MyAwesomeCompany Inc. All rights reserved.
//

The solution for that turned out to be pretty simple and it was even built-in in Xcode. It is as simple as creating an IDETemplateMacros.plist file. Let's do it!

At that point is worth mentioning that while authoring IDETemplateMacros.plist file you may use the whole range of built-in text macros. As per Xcode docs - some of the available macros are:

  • COPYRIGHT - A copyright string that uses the company name of the team for the project. If there is no company name, the string is blank.
  • DATE - The current date.
  • FILENAME - The full name of the current file.
  • ORGANIZATIONNAME - The name for your organization that appears in boilerplate text throughout your project folder.
  • YEAR - The localized year string for the current year.

The full list of available macros is available here

Let's then customize our text header to match the template above.

<?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>FILEHEADER</key>
    <string>
// Copyright (c) ___YEAR___ and Confidential to ___ORGANIZATIONNAME___ All rights reserved.
//</string>
</dict>
</plist>

Note that we have skipped the comment marker in the first line. It is automatically added by Xcode.

The last thing to do is placing IDETemplateMacros.plist file in the right location. It could be placed in one of five locations, depending on the scope it should cover.

  • Project user data: <ProjectName>.xcodeproj/xcuserdata/[username].xcuserdatad/IDETemplateMacros.plist. - using that location would cover a specific project for just a single developer.
  • Project shared data: <ProjectName>.xcodeproj/xcshareddata/IDETemplateMacros.plist- using that location would cover a specific project for the whole team using the workspace.
  • Workspace user data: <WorkspaceName>.xcworkspace/xcuserdata/[username].xcuserdatad/IDETemplateMacros.plist.- using that location would cover all projects in the workspace for just a single developer.
  • Workspace shared data: <WorkspaceName>.xcworkspace/xcshareddata/IDETemplateMacros.plist. - using that location would cover all projects in the workspace for the whole team using the workspace.
  • User Xcode data: ~/Library/Developer/Xcode/UserData/IDETemplateMacros.plist - for all projects edited by the local user.

That wide location choice is useful if you work on multiple projects with different header conventions or you want to share a default header comment format with other team members.

Enforcing the convention

Creating the files with consistent header comments is only half the battle. During work it may happen that somebody will accidentally edit the header comment or create a new file using the IDE that does not necessarily take a look in IDETemplateMacros.plist contents. Here is where SwiftLint and its File Header rule comes to play.

The rule is an opt-in rule, which means that it is disabled by default. To enable it you need to add an entry to the SwiftLint config file.

...

opt_in_rules:
-file_header

At this point you may start wondering how the rule is going to guess the expected file format. That could be also defined in SwiftLint's config.

file_header:
severity: error
required_pattern: |
                  \/\/
                  \/\/ Copyright \(c\) \d{4} and Confidential to MyAwesomeCompany Inc\. All rights reserved\.
                  \/\/

In the above example we are adding also error severity so any header comment format violation will cause emitting an error from SwiftLint. If you feel that it shouldn't - you may use warning there. Apart from setting the expected header comment format File Header rule allows to set forbidden words and patterns via forbidden_string and forbidden_pattern options.

Wrap up

In this story we have learned how to configure the consistent file header comments for all new project files that we create with Xcode. Also, we learned how to enforce common format using SwiftLint's File Header rule.

Thanks for reading!