iOS

SwiftLint: Writing good quality code in Swift

· 4 min read
SwiftLint: Writing good quality code in Swift

SwiftLint is a programming guide tool which can automatically check the code quality with certain rules such as https://github.com/github/swift-style-guide. The article will cover:

  • How to install and configure SwiftLint
  • How to use SwiftLint
  • Customise SwiftLint rules

SwiftLint installation

There are two ways of installations that we can either install swiftlint globally or per project.

Install SwiftLint globally

// install brew, if you have installed brew already, skip this step
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

// install swiftlint
brew install swiftlint

The output:

Install SwiftLint per project

If the SwiftLint was installed globally, open the Xcode project, select target and go to Build Phases:

Then click the + button as in the above screenshot to add a new Run Script Phase:

Add the following script:

if which swiftlint >/dev/null; then
  swiftlint
else
  echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
fi

Here if you installed the SwiftLint via cocoapod, replace the above script with:

"${PODS_ROOT}/SwiftLint/swiftlint"

How to use SwiftLint

If you have installed and integrated the SwiftLint to your project already, in Xcode, simply command+b:

That is it! 🥳

There are 999+ warnings and 999+ errors. 😂😂😂

The reason might be the some of the SwiftLint rules might not suitable for your project, so you can customize the rules yourself.

Integrate with Git

With the support from git, we can use SwiftLint to check our submitted code every time when we are doing a git commit, and here is how:

Find the file pre-commit under the root directory of our project, /.git/hook and replace it with the following:

#!/bin/bash

set -e

git diff --diff-filter=d --staged --name-only | grep -e '\(.*\).swift$' | while read line; do
  swiftformat "${line}";
  git add "$line";
done

swiftlint --quiet --strict

git diff --diff-filter=d --staged --name-only | grep -e '\(.*\).pbxproj$' | while read line; do
  sort-xcode-project-file "${line}";
  git add "$line";
done

By doing above, any violation of the SwiftLint rules can't be committed until we fix it.

Customise SwiftLint rules

Go to the project root directory, create a new file named .swiftlint.yml. Be care this is a hidden file you might not be able to find it in your Finder. Here is an example:

disabled_rules: # rules you don't want to use
  - trailing_comma

opt_in_rules: # rules you want to use
  - array_init
  - closure_body_length
  - closure_end_indentation

included: # include directories
  - Source

excluded: # exclude some directories, such as 3rd Carthage, pods and so on
  - Carthage
  - Pods

line_length:
  warning: 200
  error: 250

file_length:
  warning: 300
  error: 350

disabled_rules: rules you don't want to apply in your project. For more rule names and meanings, have a look at here: https://realm.github.io/SwiftLint/rule-directory.html

opt_in_rules: rules you want to apply in your project.

included: directories that you want to include.

excluded: directories that you don't want to apply SwiftLint rules, higher priority than included

line_length: how many characters are allowed in one line. >200 gives error warning, >250 gives out error.

Custom rules

Besides above rules, we can also add some custom rules, for example, only allows one space:

custom_rules:
  comma_space_rule:
    message: "Expected only one space after ',"
    severity: warning
    regex: ",[ ]{2,}"

After the customization, finally we get rid of 999+ warnings and 999+ errors.

Warnings

Please always remember to keep a copy of your files or backup before running:

Swiftlint autocorrect.

Update

I was told there are many users experiencing the same error:

Loading configuration from '.swiftlint.yml'
Linting Swift files at paths 
No lintable files found at paths: ''
Command PhaseScriptExecution failed with a nonzero exit code

This probably caused by the example .swiftlint.yml. So in the .swiftlint.yml file, we need to remove the following:

included: # include directories
	Source

Conclusion

We can either install the SwiftLint by project or globally. By the help of git, it is easily to check each of the commit to ensure the quality of the code, and of course we can customised the rules to fit in our project.

Update 2021 Dec

The run script used in Xcode might not running properly when you are using a M1 series CPU.  So add the following line (line 1):

export PATH="$PATH:/opt/homebrew/bin"  # this line

if which swiftlint >/dev/null; then
  /opt/homebrew/bin/swiftlint
else
  echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
fi