HomeiOS DevelopmentSwiftLint in Depth | Kodeco

SwiftLint in Depth | Kodeco


Constructing good apps isn’t solely about writing bug-free code. It’s additionally about writing code that requires much less effort to grasp and construct on. Think about you’re studying a powerful novel, however the font is difficult to learn and the format is messy. This novel would take extra effort to learn. And irrespective of how good the novel is, you’ll nonetheless have combined emotions about it and the writer’s abilities.

Writing code isn’t any completely different. Messy and inconsistent code takes extra effort to learn. Luckily there are instruments on the market that will help you write code that’s constant in type. Enter SwiftLint!

On this tutorial, you’ll be taught:

  • What SwiftLint is.
  • Find out how to set up SwiftLint and combine it into your initiatives.
  • A few of the coding guidelines SwiftLint checks.
  • To manage which guidelines you need to allow and disable in your undertaking.
  • Find out how to create customized guidelines.
  • Find out how to share a guidelines file throughout your completely different initiatives or the group.

Getting Began

Obtain the starter undertaking by clicking the Obtain supplies hyperlink on the prime or backside of the tutorial.

All through this tutorial, you’ll work on MarvelProductions. It lists motion pictures and TV reveals Marvel has already revealed or introduced.

Marvel Productions app running

Open the starter undertaking and have a look round.

Earlier than transferring ahead with the tutorial, change the workspace setting for the DerivedData folder of this workspace to be relative to the undertaking and never within the default location. This may obtain the SPM bundle contained in the your undertaking folder which is required for demo functions through the tutorial. Yow will discover this setting from the menu File ▸ Workspace Settings.

Changing DerivedData location setting

What Is SwiftLint?

Earlier than diving into code, it’s best to know a bit about SwiftLint. Whereas constructing your app, you’ll focus extra on the code itself as a substitute of on hold the code organized. SwiftLint is all about your code group somewhat than the logic you’re implementing. For instance SwiftLint can assist you to implement the utmost variety of traces a file or a technique ought to be. This prevents writing tremendous lengthy strategies or making a file with too many lessons or strategies inside it.

As you’re employed with completely different groups, every will probably have its personal set of tips they comply with. SwiftLint helps builders to specify a set of conventions and tips. So everybody contributing to the undertaking follows it.

How SwiftLint Works

SwiftLint goes by information in your undertaking listing and appears for sure patterns. If it finds any, it experiences them by a message on the command line.

The app runs from the command line and doesn’t have any interface of its personal. So to make use of it, you might want to do two issues:

  1. Set up SwiftLint in your laptop.
  2. Add a Run Script part in your construct steps of your Xcode undertaking which runs SwiftLint.

Putting in SwiftLint

You might have many choices to put in SwiftLint, together with CocoaPods or Homebrew. In any case, it’ll work the identical. The previous will set up it within the undertaking. So everybody engaged on the undertaking could have it whereas putting in the dependencies. The latter will set up it in your machine so you employ it in all of your initiatives.

There’s no proper or incorrect, higher or worse. It’s all a matter of choice. For this tutorial, you’ll use the latter choice, Homebrew.

Putting in Homebrew

Be aware: If you have already got Homebrew put in in your machine, skip this half.

Homebrew is a bundle supervisor for utilities on macOS. It makes life rather a lot simpler by putting in utilities you employ in your laptop and managing any dependencies these utilities could have.

Putting in Homebrew is straightforward as working this command from Terminal:


/bin/bash -c "$(curl -fsSL https://uncooked.githubusercontent.com/Homebrew/set up/HEAD/set up.sh)"

Putting in SwiftLint

To put in SwiftLint with Homebrew, run this command in Terminal after putting in Homebrew.


brew set up swiftlint

This may set up the newest model of SwiftLint.

Be aware: If you wish to set up a selected model of SwiftLint, you might want to use one thing aside from Homebrew. Both obtain the model you need from SwiftLint releases on GitHub or use Mint.

Utilizing Terminal

Now that you’ve SwiftLint put in, why not attempt it?

In Terminal, navigate to your starter undertaking. A easy manner to do this is to kind cd (with an area after cd). Then, drag and drop the folder from Finder to the Terminal window to stick the folder path in Terminal. Then press Return to execute the command.

Drawing the starter project file on the Terminal window instead of typing the path

Subsequent, kind the next into your terminal:


swiftlint

You’ll see many messages in Terminal, a few of which appear like this:


..../MarvelProductionItem.swift:66:1: warning: Line Size Violation: Line ought to be 120 characters or much less; presently it has 173 characters (line_length)

These traces are warnings and errors that SwiftLint has present in your undertaking. The final message will finish one thing like this:


Executed linting! Discovered 144 violations, 17 critical in 165 information.

This tells you what number of whole warnings and errors there are, what number of are critical, and what number of whole information have been scanned.

That is how SwiftLint works. There’s extra, after all, however so far as the way it’s executed and runs, that’s it!

Subsequent is to report these messages in Xcode and present you the file and line containing the violation.

Xcode Integration

Xcode permits messages from a command line operation to seem on prime of supply code, like syntax errors or warnings.

Open MarvelProductions.xcworkspace within the starter undertaking. Choose the MarvelProductions undertaking file on the prime of the Venture navigator. Then click on on the MarvelProductions goal and at last choose the Construct Phases tab. Click on the small + button on the top-left so as to add a brand new part and choose New Run Script Part from the menu.

Adding a new Run Script Phase from the menu

Once you construct the undertaking, it’ll run the instructions entered on this step as for those who have been getting into them on the command line. Xcode may even obtain messages from the executed command and embody them within the construct log.

Be aware: You’ll be able to change the order of the construct steps by dragging the brand new run script part and transferring it as much as execute earlier. This could prevent time to see outcomes from this script earlier than different operations.

Open up the brand new Run Script construct part and change the textual content within the giant textual content field beneath Shell with the next:


echo "${PROJECT_DIR}/MarvelProductions/DataProvider/ProductionsDataProvider.swift:39:7: error: I do not just like the identify of this class!"
exit 1

The new commands entered in the new Run Script phase

Ensure that to uncheck all of the checkboxes.

The goal of this script is to indicate you how one can report an error in one of many information within the undertaking. Here’s what’s happening within the script above:

  • echo: A Terminal command that prints out the string that follows it. It’s like print(:) in Swift. On this script, Xcode prints all of the textual content that follows it.
  • ${PROJECT_DIR}: An surroundings variable outlined by Xcode that interprets to the folder path of the undertaking file. This fashion, it doesn’t matter you probably have the undertaking in your desktop or anyplace else – the script stays the identical.
  • /MarvelProductions/DataProvider/ProductionsDataProvider.swift: The file you’re reporting an error in is ProductionsDataProvider.swift. This string is the trail of the file relative to the undertaking file.
  • :39:7:: The road and column quantity within the code file Xcode will mark with the message.
  • error:: The kind of message to indicate. It may be an error, warning or observe.
  • I don’t just like the identify of this class!: The textual content to seem within the message.

Construct the undertaking. The construct operation will fail and present you an error in ProductionsDataProvider.swift with the message I do not just like the identify of this class! and a small cursor underneath the primary letter of the category identify.

An error message appearing on ProductionsDataProvider.swift

The final line exit 1 means there was an error from the operation and Xcode ought to fail the construct. Something aside from 0 (zero) means an error, so 1 doesn’t imply something particular.

Be at liberty to vary the file, line, kind of message and the message textual content and rebuild the undertaking. However observe the colons as a result of Xcode expects the message on this particular format to indicate the message on the supply code. In any other case, a regular message will seem within the construct log.

When you’ve accomplished it, change the script with the next to combine SwiftLint into your undertaking:


export PATH="$PATH:/decide/homebrew/bin"
if which swiftlint > /dev/null; then
  swiftlint
else
  echo "warning: SwiftLint not put in, obtain from https://github.com/realm/SwiftLint"
fi

That is the really useful script to execute SwiftLint by Xcode. The primary line is essential when utilizing a Mac with an Apple Silicon processor. The script additionally checks whether or not you may have put in SwiftLint. In any other case, it prints a message to remind your group members who want to put in it.

Construct the undertaking. You’ll see all errors and warnings reported in Xcode prefer it often experiences syntax errors.

Build failed with 17 errors and 124 warnings

Time to repair up these errors! However first, let’s check out how SwiftLint defines the foundations that it follows.

What Are SwiftLint Guidelines?

Once you ran SwiftLint earlier, it reported a number of violations within the starter undertaking. You didn’t configure or specify something about what violations it ought to catch. So why did it catch these violations?

SwiftLint accommodates an enormous algorithm it may possibly detect. Not all groups have the identical tips, so these guidelines are opt-in solely. However SwiftLint has some guidelines at its disposal, that are what it applies within the undertaking.

One rule producing many warnings is orphaned_doc_comment. Yow will discover extra about it in the documentation.

Additionally, the official documentation has the listing of enabled guidelines by default and those you’ll be able to allow your self. You’ll see the way you try this shortly.

Warnings and Errors

Discover that some violations are errors and others are warnings. SwiftLint provides you management over which guidelines are errors and that are simply warnings. An error would fail the construct whereas a warning would let the construct go, however provide you with a warning to the error.

Utilizing Guidelines File

The default file SwiftLint appears for is .swiftlint.yml subsequent to the undertaking file. As a result of the file identify begins with a dot, the simplest approach to create it’s by Terminal.

Return to Terminal and make sure you’re on the trail of the starter undertaking. Then, kind the next command:


contact .swiftlint.yml

This creates a hidden file named .swiftlint.yml. To view the file, go to the undertaking folder in Finder. Press Shift-Command-, to indicate hidden information in Finder.

Starter project with the hidden file .swiftlint.yml

Construction of the Guidelines File

The file you created is the place you configure all the things about SwiftLint. You’ll be able to disable a number of the guidelines which might be on by default and allow others. Or you’ll be able to specify solely a selected algorithm to allow. The primary method makes use of the default guidelines specified internally in SwiftLint. These default guidelines are topic to vary in response to the model of SwiftLint. The second method utterly ignores all of the default guidelines and specifies solely those you need. This method would take pleasure in the algorithm not altering when SwiftLint is up to date.

Neither choice is healthier. It’s all about how you favor to manage it.

Within the guidelines file, you may also specify information and folders to disregard. For instance, you may need some third-party libraries within the undertaking folder or some generated information you don’t need to cowl within the checks.

Excluded Checklist

The present undertaking installs the Nuke library through SPM which downloads to the undertaking listing. SwiftLint is reporting a major variety of violations in it.

Be aware: If you don’t discover any violations from inside Nuke then it’s as a result of your DerivedData folder will not be set to be within the undertaking listing. Try the Getting Began part of this tutorial and be sure you adopted the directions there.

Open .swiftlint.yml, which ought to be empty, and enter the next:


excluded:
  - DerivedData

Save the file, then construct the undertaking.

Discover that the variety of violations dropped considerably! You now have solely the SwiftLint violations out of your undertaking’s code.

Number of errors and warnings dropped after excluding the DerivedData folder

Disabling Guidelines

One rule is essential for a undertaking: orphaned_doc_comment. This rule experiences a violation on each remark line.

Return to the foundations file and add the next on the finish:


disabled_rules:
  - orphaned_doc_comment

Updated rules file with excluded DerivedData folder and excluded rules

Save the file and construct the undertaking.

Now, that’s way more reasonable to work with.

Configuring Guidelines

Your undertaking nonetheless doesn’t construct because of the three errors SwiftLint is reporting. When you’re introducing SwiftLint into a big undertaking a group has been engaged on for years, you’ll have many greater than three errors. It’s not reasonable to utterly fail the undertaking at this level. It could be extra handy for you and the group to cut back the severity of these violations from errors to warnings to unblock the entire undertaking. That is the place rule configurations are available in.

The 2 error-generating guidelines are force_cast and identifier_name. You’ll be able to configure guidelines to match your wants.

On the finish of the foundations file, add the next:


force_cast: warning # 1

identifier_name: # 2
  excluded:
    - i
    - id
    - x
    - y
    - z

The configuration you added consists of two elements:

  1. force_cast has just one configuration doable, which is to set it to both warning or error.
  2. identifier_name permits for extra configurations. The listing of variable names permits them to exclude. The undertaking makes use of i, however the others are additionally frequent variable names that break the rule however are acceptable to us.

Construct the undertaking, and now it can lastly succeed. The 2 errors from force_cast are exhibiting as warnings. As for the one from identifier_name, it has disappeared.

Disabling Guidelines By way of Code

There’s one other approach to disable a rule. You’ll be able to ignore a rule by including a remark earlier than the code block that produces the violation. For instance:


// swiftlint:disable [rule_name], [another_rule_name], ....

This disables the desired guidelines utterly. Ranging from this remark till the tip of the file or till you allow them once more:


// swiftlint:allow [rule_name], [another_rule_name], ....

There’s additionally the choice to disable a rule that’s showing within the subsequent line and the following line solely:


// swiftlint:disable:subsequent [rule_name], [another_rule_name], ....

But when the rule isn’t triggered within the subsequent line, SwiftLint will warn that this disable is pointless. This may be helpful so that you don’t fear about re-enabling the rule once more.

Within the starter undertaking, you’ll discover a few SwiftLint disables. These guidelines didn’t play nicely with Regex expressions and don’t apply there. Because of this it’s necessary to grasp the foundations and know after they make sense and after they don’t.

Fixing the Violations

Nearly each time, the message from SwiftLint describes why there was a violation.

For instance, discover the warning within the Difficulty navigator:


Comma Spacing Violation: There ought to be no house earlier than and one after any comma. (comma)

Faucet this warning. In ProductionsListView.swift, you’ll see there’s an area between MarvelProductionItem.pattern() and the comma within the first two gadgets. Take away these pointless areas:


ProductionsListView(productionsList: [
  MarvelProductionItem.sample(),
  MarvelProductionItem.sample(),
  MarvelProductionItem.sample(),
  MarvelProductionItem.sample()
])

Construct the undertaking. These warnings have disappeared!

Subsequent is the warning for line_length. The road inflicting this warning in MarvelProductionItem.swift is:


posterURL: URL(string: "https://m.media-amazon.com/pictures/M/MV5BYTc5OWNhYjktMThlOS00ODUxLTgwNDQtZjdjYjkyM2IwZTZlXkEyXkFqcGdeQXVyNTA3MTU2MjE@._V1_Ratio0.6800_AL_.jpg"),

This can be a prolonged line, however it may be complicated for those who break a URL into many traces. For that, configure line_length to disregard URLs. Add the next rule configuration on the finish of the foundations file:


line_length:
  ignores_urls: true
  ignores_function_declarations: true
  ignores_comments: true

This ignores the road size rule for URLs, perform declarations and feedback.

Now open ProductionYearInfo.swift, and see the primary case inside ProductionYearInfo is producing a warning:


case produced(yr : Int)

The colon rule checks that there’s no pointless house earlier than the colon and just one house after it. As you see within the line talked about, there’s an area between the yr and the colon. Eradicating this house resolves the warning:


case produced(yr: Int)

Subsequent, why not repair the force-casting warning as soon as and for all?

This rule is effective as a result of it retains you attentive about one thing that would crash your app. Power casting will work positive so long as the info is as anticipated, however as soon as it’s not, your app will crash.

In PremieredOnInfo.swift, you may have two situations of power casting:


let end result = match.first?.worth as! Substring

A secure approach to keep away from it’s to make use of elective casting whereas offering a price with the nil-coalescing operator. This reduces the variety of code modifications by avoiding making the property elective and never forcing the casting. Change the 2 situations utilizing the power casting to the next:


let end result = match.first?.worth as? Substring ?? ""

The final two warnings are in ProductionsDataProvider.swift. Between the import statements and the disabled remark, there are three vertical areas. The rule vertical_whitespace checks that you just don’t have pointless vertical areas. Delete the additional two traces.

Lastly, SwiftLint is complaining that loadData() is a protracted perform. That is true, however the default worth of 40 traces is just too quick, and we’ve determined that the utmost perform physique ought to be 70 traces. Add the next to the foundations file:


function_body_length:
    warning: 70

Construct the undertaking. Lastly, you haven’t any extra warnings.

However that doesn’t imply the undertaking is in a really perfect state. It’s positively in higher form, however you’ll be able to nonetheless enhance it. You solely mounted the violations the default guidelines detected. SwiftLint has extra to report on this undertaking.

Enabling Extra Guidelines

Your group has agreed so as to add a number of extra guidelines on prime of the defaults and never all of them with the default configurations of SwiftLint:

Add the next to the foundations file:


opt_in_rules:
  - indentation_width
  - force_unwrapping
  - redundant_type_annotation
  - force_try
  - operator_usage_whitespace

indentation_width:
  indentation_width: 2

Construct the undertaking. You see eight new warnings. Just one is about indentation. The remaining are due to power unwrapping.

Let’s repair the indentation one first. Faucet the indentation warning to open ProductionsDataProvider.swift. Go to the warning there, then align return [] with the catch above it:


} catch {
  return []
}

A couple of of the power castings in ProductionYearInfo.swift are as a result of some Int initializations are force-unwrapped. Int(:) can produce nil if the string handed will not be a quantity. For any purpose, if the worth handed to the constructor had an alphabetical character, the produced worth could be nil, and the power unwrapping would trigger a crash.

You’ll repair this utilizing the nil-coalescing operator. However you’ll attempt a trick to unravel multiple warning with a single search and change, utilizing common expressions.

From the undertaking navigator column, choose the Discover tab. Change Discover to Exchange and from Textual content to Common Expression. Within the first textual content area, enter Int((.+))! and in the second, enter Int($1) ?? 0.

Using a regular expression to change multiple code instances together

By protecting the enhancing cursor on the primary textual content area and urgent return on the keyboard, Xcode will search and received’t apply the substitute. That is helpful if you wish to examine earlier than urgent the “Exchange all” button.

You’ll have 5 search outcomes. All have a power unwrapping on an Int(:) name. Exchange all.

Construct the undertaking to verify all the things is OK. The construct succeeds, and you’ve got solely two warnings left. How did this regex magic work?

The expression you entered Int((.+))! appears for any textual content beginning with Int(. As a result of the spherical brackets are precise characters utilized in common expressions, you should escape them.

The internal set of parentheses is a seize group. The matched expression inside is saved for later use, and also you entry it with $1, which you entered within the substitute string. The remainder of the expression is the closing parentheses and the power unwrapping operator, )!.

The seize group lets you retailer the property despatched to the integer constructor and reuse this property within the new substitute string. You solely need to concentrate on force-unwraps of Int(:). When you seek for )! solely throughout the undertaking, you’ll change locations you shouldn’t.

As for the final two warnings, discover the primary in PremieredOnInfo.swift and change the offending code with:


let date = formatter.date(from: dateString) ?? Date()

Then discover the second in ProductionItemView.swift and change the offending code with:


Textual content("(String(format: "%.1f", productionItem.imdbRating ?? 0))")

All of the warnings are gone!

Make Your Personal Guidelines

One other cool function SwiftLint helps is the flexibility to create your individual guidelines. SwiftLint treats guidelines you create the identical manner it handles its built-in guidelines. The one factor you’ll want is to create a daily expression for it.

The rule your group desires to use is about declaring empty arrays and dictionaries. You need to outline the kind, and it mustn’t depend on inference:


// Not OK
var array = [Int]()
var dict = [String: Int]()

// OK
var array: [Int] = []
var dict: [String: Int] = [:]

Add the next to the foundations file:


custom_rules:
  array_constructor: # 1
    identify: "Array/Dictionary initializer" # 2
    regex: '[let,var] .+ = ([.+]())' # 3
    capture_group: 1 # 4
    message: "Use specific kind annotation when initializing empty arrays and dictionaries" # 5
    severity: warning # 6

custom_rules is one other part within the guidelines file the place you’ll be able to declare your individual algorithm.

Here’s a step-by-step description of the above customized rule:

  1. You begin by creating an identifier for the brand new rule and embody all its properties beneath.
  2. identify: The identify for this rule.
  3. regex: You outline the common expression for the violation you need to seek for.
  4. capture_group: If a part of the common expression match is the place the violation is and also you’re utilizing seize teams to concentrate on it, you specify the variety of the seize group right here. When you’re not utilizing seize teams, you don’t want to incorporate this property.
  5. message: The message you need to present to explain the difficulty.
  6. severity: Set to error or warning.

Construct the undertaking to see this new rule in motion:

The new custom rule showing two warnings in Xcode

To repair these two warnings, you may have a direct textual content substitute for:


// In ProductionsDataProvider.swift
var marvelProductions = [MarvelProductionItem]()

// In ProductionsListView.swift
var productionsList = [MarvelProductionItem]()

To:


var marvelProductions: [MarvelProductionItem] = []
var productionsList: [MarvelProductionItem] = []

Distant Guidelines

SwiftLint has an superior function that helps hold guidelines centralized for the entire group. The foundations file doesn’t must be beside the undertaking file or named .swiftlint.yml. You’ll be able to transfer the file to anyplace you need in your machine. You even can retailer it on a server and go its path as an argument to the swiftlint command:


swiftlint --config [yml file path or url]

Why not give it a attempt?

Open Terminal and navigate to your undertaking’s path. Then run this command:


mv .swiftlint.yml ~/swiftlintrules.yml

This strikes .swiftlint.yml from the present listing to the foundation of the consumer folder and renames the file to swiftlintrules.yml.

Return to your undertaking in Xcode and replace the run script to the next:


export PATH="$PATH:/decide/homebrew/bin"
if which swiftlint > /dev/null; then
  swiftlint --config ~/swiftlintrules.yml
else
  echo "warning: SwiftLint not put in, obtain from https://github.com/realm/SwiftLint"
fi

Construct the undertaking. Sadly, it’ll give some warnings and errors. Don’t panic. Recordsdata reporting violations are from the code information within the folder you excluded earlier.

Within the new guidelines file, change the exclude part to the next:


excluded:
  - ${PWD}/DerivedData

All you probably did was have the exclude folders with a full path. PWD, or Print Working Listing, interprets to the undertaking listing when Xcode runs the command.

Construct the undertaking once more. It’ll succeed. :]

The place to Go From Right here?

You’ll be able to obtain the finished undertaking information by clicking the Obtain supplies button on the prime or backside of this tutorial.

SwiftLint could be a highly effective software in your undertaking. It may possibly additionally frustrate group members if somebody provides guidelines as a result of extra guidelines enhance code. However this may be incorrect. Each rule ought to have a superb justification, and the group ought to determine collectively.

Kodeco has SwiftLint guidelines to comply with in all of the iOS content material throughout the web site. It’s based mostly on all the corporate’s coding tips.

In addition to checking your code, SwiftLint has extra capabilities to discover:

It’s worthwhile to undergo the foundations SwiftLint has at its disposal. Every rule has its clarification of what’s going to set off it and what received’t.

We hope you loved this tutorial. When you’ve got any questions or feedback, please be part of the discussion board dialogue beneath!

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments