Constructing good apps isn’t solely about writing bug-free code. It’s additionally about writing code that requires much less effort to know and construct on. Think about you’re studying a powerful novel, however the font is tough 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. Happily there are instruments on the market that can assist you write code that’s constant in type. Enter SwiftLint!
On this tutorial, you’ll be taught:
- What SwiftLint is.
- Learn 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 mission.
- Learn how to create customized guidelines.
- Learn how to share a guidelines file throughout your totally different initiatives or the workforce.
Getting Began
Obtain the starter mission 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 exhibits Marvel has already revealed or introduced.
Open the starter mission and have a look round.
Earlier than shifting 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. You will discover this setting from the menu File ▸ Workspace Settings.
What Is SwiftLint?
Earlier than diving into code, you must know a little bit about SwiftLint. Whereas constructing your app, you’ll focus extra on the code itself as an alternative of on the right way to hold the code organized. SwiftLint is all about your code group slightly than the logic you’re implementing. For instance SwiftLint may help you to implement the utmost variety of strains a file or a way needs to be. This prevents writing tremendous lengthy strategies or making a file with too many courses 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 by means of information in your mission listing and appears for sure patterns. If it finds any, it reviews them by means of 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:
- Set up SwiftLint in your pc.
- Add a Run Script section in your construct steps of your Xcode mission which runs SwiftLint.
Putting in SwiftLint
You’ve 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 utilize it in all of your initiatives.
There’s no proper or unsuitable, higher or worse. It’s all a matter of desire. For this tutorial, you’ll use the latter possibility, 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 lots simpler by putting in utilities you utilize in your pc 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
It will set up the newest model of SwiftLint.
Utilizing Terminal
Now that you’ve SwiftLint put in, why not attempt it?
In Terminal, navigate to your starter mission. A easy manner to try this is to sort 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.
Subsequent, sort 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; at the moment it has 173 characters (line_length)
These strains are warnings and errors that SwiftLint has present in your mission. The final message will finish one thing like this:
Finished linting! Discovered 144 violations, 17 severe in 165 information.
This tells you what number of complete warnings and errors there are, what number of are severe, and what number of complete 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 mission. Choose the MarvelProductions mission file on the prime of the Venture navigator. Then click on on the MarvelProductions goal and eventually choose the Construct Phases tab. Click on the small + button on the top-left so as to add a brand new section and choose New Run Script Section from the menu.
If you construct the mission, it’ll run the instructions entered on this step as when you had been coming into them on the command line. Xcode will even obtain messages from the executed command and embrace them within the construct log.
Be aware: You may change the order of the construct steps by dragging the brand new run script section and shifting it as much as execute earlier. This may prevent time to see outcomes from this script earlier than different operations.
Open up the brand new Run Script construct section 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 title of this class!"
exit 1
Be sure to uncheck all of the checkboxes.
The intention 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 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 atmosphere 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 title 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 title of this class!
and a small cursor beneath the primary letter of the category title.
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 happy to vary the file, line, sort 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 regular 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:/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 recommended script to execute SwiftLint through 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 workforce members who want to put in it.
Construct the mission. You’ll see all errors and warnings reported in Xcode prefer it normally reviews syntax errors.
Time to repair up these errors! However first, let’s check out how SwiftLint defines the foundations that it follows.
What Are SwiftLint Guidelines?
If 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 will probably 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. You will discover extra about it in the documentation.
Additionally, the official documentation has the checklist 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 cross, however provide you with a warning to the error.
Utilizing Guidelines File
The default file SwiftLint appears for is .swiftlint.yml subsequent to the mission file. As a result of the file title begins with a dot, the simplest approach to create it’s by means of Terminal.
Return to Terminal and make sure you’re on the trail of the starter mission. Then, sort 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.
Construction of the Guidelines File
The file you created is the place you configure every part about SwiftLint. You may disable a number of the guidelines which can 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 fully ignores all of the default guidelines and specifies solely those you need. This method would get pleasure from the algorithm not altering when SwiftLint is up to date.
Neither possibility is best. 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 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 is just not set to be within the mission listing. Take a look at the Getting Began part of this tutorial and be sure you 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.
Disabling Guidelines
One rule is essential for a mission: orphaned_doc_comment. This rule reviews a violation on each remark line.
Return to the foundations file and add the next on the finish:
disabled_rules:
- orphaned_doc_comment
Save the file and construct the mission.
Now, that’s far more sensible to work with.
Configuring Guidelines
Your mission nonetheless doesn’t construct as a result of three errors SwiftLint is reporting. In the event you’re introducing SwiftLint into a big mission a workforce has been engaged on for years, you’ll have many greater than three errors. It’s not sensible to fully fail the mission at this level. It will be extra handy for you and the workforce 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 may 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 components:
- force_cast has just one configuration potential, which is to set it to both warning or error.
-
identifier_name permits for extra configurations. The checklist 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 would lastly succeed. The 2 errors from force_cast are exhibiting as warnings. As for the one from identifier_name, it has disappeared.
Disabling Guidelines Via Code
There’s one other approach to disable a rule. You may 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 nicely with Regex expressions and don’t apply there. That is why it’s essential to know the foundations and know after they make sense and after 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 Problem navigator:
Comma Spacing Violation: There needs 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 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/photographs/M/MV5BYTc5OWNhYjktMThlOS00ODUxLTgwNDQtZjdjYjkyM2IwZTZlXkEyXkFqcGdeQXVyNTA3MTU2MjE@._V1_Ratio0.6800_AL_.jpg"),
It is a prolonged line, however it may be complicated when you break a URL into many strains. 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(12 months : 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 12 months
and the colon. Eradicating this house resolves the warning:
case produced(12 months: 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 would crash your app. Pressure casting will work high quality 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 cases of power casting:
let end result = match.first?.worth as! Substring
A secure approach 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 modifications by avoiding making the property non-compulsory and never forcing the casting. Change the 2 cases 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 strains.
Lastly, SwiftLint is complaining that loadData()
is a protracted perform. That is true, however the default worth of 40
strains is just too quick, and we’ve determined that the utmost perform physique needs to be 70 strains. Add the next to the foundations file:
function_body_length:
warning: 70
Construct the mission. Lastly, you don’t have any extra warnings.
However that doesn’t imply the mission is in a really perfect 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 workforce has agreed so as to add a couple 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 mission. You see eight new warnings. Just one is about indentation. The remainder 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 []
}
Just a few 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 is just not a quantity. For any cause, if the worth handed to the constructor had an alphabetical character, the produced worth can 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 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 Exchange and from Textual content to Common Expression. Within the first textual content area, enter Int((.+))!
and in the second, enter Int($1) ?? 0
.
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 “Exchange all” button.
You’ll have 5 search outcomes. All have a power unwrapping on an Int(:)
name. Exchange all.
Construct the mission to ensure every part 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 could 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 give attention to force-unwraps of Int(:)
. In the event 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 characteristic SwiftLint helps is the power to create your personal 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 workforce 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
title: "Array/Dictionary initializer" # 2
regex: '[let,var] .+ = ([.+]())' # 3
capture_group: 1 # 4
message: "Use specific sort 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:
- You begin by creating an identifier for the brand new rule and embrace all its properties beneath.
- title: The title for this rule.
- regex: You outline the common expression for the violation you need to seek for.
- capture_group: If a part of the common expression match is the place the violation is and also you’re utilizing seize teams to give attention to it, you specify the variety of the seize group right here. In the event you’re not utilizing seize teams, you don’t want to incorporate this property.
- message: The message you need to present to explain the difficulty.
- severity: Set to error or warning.
Construct the mission to see this new rule in motion:
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 characteristic that helps hold guidelines centralized for the entire workforce. The principles file doesn’t should be beside the mission file or named .swiftlint.yml. You may transfer the file to anyplace you need in your machine. You even can retailer it on a server and cross 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 mission’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 mission 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 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 may obtain the finished mission information by clicking the Obtain supplies button on the prime or backside of this tutorial.
SwiftLint is usually a highly effective device in your mission. It could actually additionally frustrate workforce members if somebody provides guidelines as a result of extra guidelines enhance code. However this may be unsuitable. Each rule ought to have a very good justification, and the workforce ought to determine collectively.
Kodeco has SwiftLint rules to comply with in all of the iOS content material throughout the web site. It’s primarily based on all the company’s coding guidelines.
In addition to checking your code, SwiftLint has extra capabilities to discover:
It’s priceless to undergo the foundations SwiftLint has at its disposal. Every rule has its rationalization of what is going to set off it and what gained’t.
We hope you loved this tutorial. When you have any questions or feedback, please be a part of the discussion board dialogue under!