Linting code is a crucial part of your programming, especially if you’re more than an indie developer. Unfortunately, despite the number of calls you have and agree on how you’re going to format your Swift code, you’ll always get inconsistencies between you and your fellow engineers.
It’s never intentional, but you can be sure that someone has tabs instead of spaces or will put the curly brace on the following line.
Code Linting is a tool that will throw compiler warnings/errors or in-line suggestions based on the rules you set from either the community or among your team.
SwiftLint
SwiftLint is the most popular tool in the iOS community, and the Github repository is open-source, which means the community can define and vote on the rules that people can get by default.
However, you can also define your own custom rules, and you will explore doing that in this tutorial.
Getting Started
You should start by opening your iOS application within Xcode.
You can install SwiftLint using either CocoaPods, HomeBrew or Mint. Let’s go with the recommended way using CocoaPods.
- Open your PodFile.
pod 'SwiftLint'
You should add the above dependency to your PodFile and run the following command:
pod install
This will go ahead and install SwiftLint as a dependency inside your Xcode Project.
Running SwiftLint on Build
The best way to execute a linting tool is to have it run every time you build the Xcode Project. It means that the SwiftLint rules will be applied every time you compile your code.
- Open Xcode.
- Click on the Project file inside your Navigator.
- Click on your App Target and then click on Build Phases
- Click on the + sign and click on New Run Script Phase
if which swiftlint >/dev/null; then
swiftlint
else
echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
fi
You should paste this code inside the Run Script.
This code will execute SwiftLint or fail for anyone who is yet to install SwiftLint.
You might want to move SwiftLint elsewhere, or you might want to have this running on CI and outside local development. But having it locally here means that issues are found quickly and locally.
Build your Xcode Project, and SwiftLint will now be active.
SwiftLint Custom Rules
As mentioned previously, the community defines the rules here, and they are changed/improved with a voting system that you can contribute.
However, sometimes your codebase might have specific requirements or not necessarily agree with the community.
In which case, you can define your own custom rules.
You need to create a brand new file inside your project root folder.
cd YourRootFolder
touch .swiftlint.yml
This command will navigate to your project folder and create a new file named swiftlint.yml
.
Go ahead and open this new file.
# By default, SwiftLint uses a set of sensible default rules you can adjust:
disabled_rules: # rule identifiers turned on by default to exclude from running
- colon
- comma
- control_statement
opt_in_rules: # some rules are turned off by default, so you need to opt-in
- empty_count # Find all the available rules by running: `swiftlint rules`
# Alternatively, specify all rules explicitly by uncommenting this option:
# only_rules: # delete `disabled_rules` & `opt_in_rules` if using this
# - empty_parameters
# - vertical_whitespace
included: # paths to include during linting. `--path` is ignored if present.
- Source
excluded: # paths to ignore during linting. Takes precedence over `included`.
- Carthage
- Pods
- Source/ExcludedFolder
- Source/ExcludedFile.swift
- Source/*/ExcludedFile.swift # Exclude files with a wildcard
analyzer_rules: # Rules run by `swiftlint analyze` (experimental)
- explicit_self
# configurable rules can be customized from this configuration file
# binary rules can set their severity level
force_cast: warning # implicitly
force_try:
severity: warning # explicitly
# rules that have both warning and error levels, can set just the warning level
# implicitly
line_length: 110
# they can set both implicitly with an array
type_body_length:
- 300 # warning
- 400 # error
# or they can set both explicitly
file_length:
warning: 500
error: 1200
# naming rules can set warnings/errors for min_length and max_length
# additionally they can set excluded names
type_name:
min_length: 4 # only warning
max_length: # warning and error
warning: 40
error: 50
excluded: iPhone # excluded via string
allowed_symbols: ["_"] # these are allowed in type names
identifier_name:
min_length: # only min_length
error: 4 # only error
excluded: # excluded via string array
- id
- URL
- GlobalAPIKey
reporter: "xcode" # reporter type (xcode, json, csv, checkstyle, codeclimate, junit, html, emoji, sonarqube, markdown, github-actions-logging)
This is an example taken directly from SwiftLint with some ideas on customising SwiftLint. Of course, you can go ahead and make some changes.
line_length: 110
file_length:
warning: 500
error: 1200
You can go ahead and set the above rules. You have gone with a line length of 110 and a file size of 500-1200 with different levels of warning/error.
This is an excellent example of how you can customise this even further.
Disable Rules
You can also disable specific rules within your codebase, this is super useful if you want to disable a specific piece of code rather than the whole Swift file.
// swiftlint:disable:next line_length
func largeFunction() {
// Large Function
}
The above example will disable the rule line_length
for the next piece of code. You can also disable rules for an entire block of code:
// swiftlint:disable colon
func largeFunction() {
}
func anotherFunction() {
}
// swiftlint:enable colon
Your example above will disable the rule colon
for the entire block, but don’t forget to enable it again so the remainder of the file is covered.
What’s Next?
SwiftLint can be a great tool to implement into your workflow; it will make your codebase much more consistent and format the same way for all engineers. It’s about defining the rules with your team and allowing the tooling to create a level of enforcement.
Finally, the CLI tool is convenient, and so I recommend you install this using HomeBrew:
brew install SwiftLint