Thursday, September 28, 2023
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 expertise.

Writing code is not any totally different. Messy and inconsistent code takes extra effort to learn. Fortuitously there are instruments on the market that will help you write code that’s constant in model. Enter SwiftLint!

On this tutorial, you’ll study:

  • What SwiftLint is.
  • Tips on how to set up SwiftLint and combine it into your initiatives.
  • Among the coding guidelines SwiftLint checks.
  • To regulate which guidelines you need to allow and disable in your mission.
  • Tips on how to create customized guidelines.
  • Tips on how to share a guidelines file throughout your totally different initiatives or the staff.

Getting Began

Obtain the starter mission by clicking the Obtain supplies hyperlink on the high or backside of the tutorial.

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

Marvel Productions app running

Open the starter mission 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 mission and never within the default location. It will obtain the SPM package deal contained in the your mission folder which is required for demo functions throughout 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 is best to know a bit of about SwiftLint. Whereas constructing your app, you’ll focus extra on the code itself as an alternative of on find out how to maintain the code organized. SwiftLint is all about your code group fairly than the logic you’re implementing. For instance SwiftLint might help you to implement the utmost variety of traces a file or a way needs 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 totally different groups, every will doubtless 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 mission follows it.

How SwiftLint Works

SwiftLint goes via information in your mission listing and appears for sure patterns. If it finds any, it studies them via 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’ll want to do two issues:

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

Putting in SwiftLint

You have got 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 mission. So everybody engaged on the mission 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 improper, higher or worse. It’s all a matter of desire. 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 package deal supervisor for utilities on macOS. It makes life loads simpler by putting in utilities you employ in your pc and managing any dependencies these utilities might 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

It will set up the newest model of SwiftLint.

Be aware: If you wish to set up a particular model of SwiftLint, you’ll 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 got SwiftLint put in, why not strive it?

In Terminal, navigate to your starter mission. A easy approach to try 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 to be this:


..../MarvelProductionItem.swift:66:1: warning: Line Size Violation: Line needs 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 mission. The final message will finish one thing like this:


Carried out linting! Discovered 144 violations, 17 severe in 165 information.

This tells you what number of whole warnings and errors there are, what number of are severe, 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 high of supply code, like syntax errors or warnings.

Open MarvelProductions.xcworkspace within the starter mission. Choose the MarvelProductions mission file on the high of the Mission 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 Section from the menu.

Adding a new Run Script Phase from the menu

Once you construct the mission, it’ll run the instructions entered on this step as in case you had been coming into them on the command line. Xcode can even obtain messages from the executed command and embody them within the construct log.

Be aware: You possibly can change the order of the construct steps by dragging the brand new run script part and transferring it as much as execute earlier. This will 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 massive 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

Make sure that to uncheck all of the checkboxes.

The goal of this script is to point out you how one can report an error in one of many information within the mission. Here’s what’s occurring 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 mission file. This manner, it doesn’t matter if in case you have the mission in your desktop or anyplace else – the script stays the identical.
  • /MarvelProductions/DataProvider/ProductionsDataProvider.swift: The file you might be reporting an error in is ProductionsDataProvider.swift. This string is the trail of the file relative to the mission file.
  • :39:7:: The road and column quantity within the code file Xcode will mark with the message.
  • error:: The kind of message to point out. It may be an error, warning or be aware.
  • I don’t just like the identify of this class!: The textual content to seem within the message.

Construct the mission. 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 below 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 mission. However be aware the colons as a result of Xcode expects the message on this particular format to point out the message on the supply code. In any other case, a typical message will seem within the construct log.

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


export PATH="$PATH:/choose/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 helpful script to execute SwiftLint via Xcode. The primary line is essential when utilizing a Mac with an Apple Silicon processor. The script additionally checks whether or not you’ve gotten put in SwiftLint. In any other case, it prints a message to remind your staff members who want to put in it.

Construct the mission. You’ll see all errors and warnings reported in Xcode prefer it often studies 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 mission. 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 well 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 mission.

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 do 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 warn you to the error.

Utilizing Guidelines File

The default file SwiftLint seems for is .swiftlint.yml subsequent to the mission file. As a result of the file identify begins with a dot, the best method to create it’s via Terminal.

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


contact .swiftlint.yml

This creates a hidden file named .swiftlint.yml. To view the file, go to the mission folder in Finder. Press Shift-Command-, to point out 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 possibly can disable a number of the guidelines which can be on by default and allow others. Or you’ll be able to specify solely a specific algorithm to allow. The primary method makes use of the default guidelines specified internally in SwiftLint. These default guidelines are topic to vary in accordance with the model of SwiftLint. The second method fully 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 best. It’s all about how you favor to regulate it.

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

Excluded Checklist

The present mission installs the Nuke library through SPM which downloads to the mission listing. SwiftLint is reporting a big 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 mission listing. Try the Getting Began part of this tutorial and be sure to adopted the directions there.

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


excluded:
  - DerivedData

Save the file, then construct the mission.

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

Number of errors and warnings dropped after excluding the DerivedData folder

Disabling Guidelines

One rule is essential for a mission: orphaned_doc_comment. This rule studies 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 mission.

Now, that’s way more life like to work with.

Configuring Guidelines

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

The 2 error-generating guidelines are force_cast and identifier_name. You possibly can 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 potential, 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 mission makes use of i, however the others are additionally frequent variable names that break the rule however are acceptable to us.

Construct the mission, and now it’s going to 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 Code

There’s one other method to disable a rule. You possibly can 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 required guidelines fully. Ranging from this remark till the top 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 subsequent 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 mission, you’ll discover a few SwiftLint disables. These guidelines didn’t play effectively with Regex expressions and don’t apply there. Because of this it’s vital to grasp the foundations and know once they make sense and once they don’t.

Fixing the Violations

Virtually 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 needs to be no area 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 objects. Take away these pointless areas:


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

Construct the mission. 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/photos/M/MV5BYTc5OWNhYjktMThlOS00ODUxLTgwNDQtZjdjYjkyM2IwZTZlXkEyXkFqcGdeQXVyNTA3MTU2MjE@._V1_Ratio0.6800_AL_.jpg"),

This can be a prolonged line, however it may be complicated in case you 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, operate 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 area earlier than the colon and just one area after it. As you see within the line talked about, there’s an area between the yr and the colon. Eradicating this area resolves the warning:


case produced(yr: Int)

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

This rule is efficacious as a result of it retains you attentive about one thing that might crash your app. Drive casting will work high quality so long as the information is as anticipated, however as soon as it’s not, your app will crash.

In PremieredOnInfo.swift, you’ve gotten two cases of pressure casting:


let outcome = match.first?.worth as! Substring

A protected method to keep away from it’s to make use of non-compulsory casting whereas offering a price with the nil-coalescing operator. This reduces the variety of code adjustments by avoiding making the property non-compulsory and never forcing the casting. Change the 2 cases utilizing the pressure casting to the next:


let outcome = 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 an extended operate. That is true, however the default worth of 40 traces is just too brief, and we’ve determined that the utmost operate physique needs to be 70 traces. Add the next to the foundations file:


function_body_length:
    warning: 70

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

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

Enabling Extra Guidelines

Your staff has agreed so as to add a number of extra guidelines on high 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 mission. You see eight new warnings. Just one is about indentation. The remaining are due to pressure 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 number of of the pressure 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 pressure unwrapping would trigger a crash.

You’ll repair this utilizing the nil-coalescing operator. However you’ll strive a trick to resolve a couple of warning with a single search and change, utilizing common expressions.

From the mission navigator column, choose the Discover tab. Change Discover to Change 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 modifying cursor on the primary textual content area and urgent return on the keyboard, Xcode will search and gained’t apply the substitute. That is helpful if you wish to examine earlier than urgent the “Change all” button.

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

Construct the mission to ensure 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((.+))! seems for any textual content beginning with Int(. As a result of the spherical brackets are precise characters utilized in common expressions, you need to escape them.

The inside 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 pressure unwrapping operator, )!.

The seize group permits you to 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(:). Should you seek for )! solely throughout the mission, 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 power to create your personal guidelines. SwiftLint treats guidelines you create the identical approach it handles its built-in guidelines. The one factor you’ll want is to create a daily expression for it.

The rule your staff 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 express 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 personal 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. Should 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 problem.
  6. severity: Set to error or warning.

Construct the mission to see this new rule in motion:

The new custom rule showing two warnings in Xcode

To repair these two warnings, you’ve gotten 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 maintain guidelines centralized for the entire staff. The principles file doesn’t have to be beside the mission file or named .swiftlint.yml. You possibly can 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 strive?

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


mv .swiftlint.yml ~/swiftlintrules.yml

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

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


export PATH="$PATH:/choose/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 mission. 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 mission listing when Xcode runs the command.

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

The place to Go From Right here?

You possibly can obtain the finished mission information by clicking the Obtain supplies button on the high or backside of this tutorial.

SwiftLint generally is a highly effective device in your mission. It could possibly additionally frustrate staff members if somebody provides guidelines as a result of extra guidelines enhance code. However this may be improper. Each rule ought to have a great justification, and the staff ought to resolve collectively.

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

Apart from checking your code, SwiftLint has extra capabilities to discover:

It’s invaluable to undergo the foundations SwiftLint has at its disposal. Every rule has its rationalization of what’s going to set off it and what gained’t.

We hope you loved this tutorial. You probably have any questions or feedback, please be part of the discussion board dialogue beneath!



Supply hyperlink

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments