Using SwiftLint to reduce code smell on Xcode.

(…and increase over all consistency in our code base.)

2020 @ https://www.google.com/maps?cid=3113512418631351453

I — Intro

I’m a fan of procedures, documentation, unsmelly and organised code. One of my biggest allies to ensure I don’t forget follow the rules is Swiftlint.

Swiftlint is a tool to enforce Swift style and conventions, loosely based on GitHub’s Swift Style Guide.

Swiftlint can friendly “tip” you…

Image 1 : SwiftLint warning

…or just forbid you some coding behaviours.

Image 2: SwiftLint error

II — Extra motivation.

Image 3 — Basic design language for images

Imagine you have an app with a particular design language (see image 3) and you want to prevent doing things like:

var avatarView = UIImageView(image: UIImage(named: “avatar.1”))

and promote instead:

var avatarView = UIImageView(image: ImageNames.avatar.image)

A simple way is to define a rule like:

no_hardCodedImages:
included: “.*\\.swift”
name: “Fordiden hardCoded images”
regex: “UIImage[(]named:”
message: “Don’t use hardCoded images”
severity: error

And the next time that kind of code appear you are presented with the following compile error:

Saying so, SwiftLint is powerful ally to prevent unwanted/unsafe code fingerprint.

This article is about some of the rules I use, and why.

III — Some of my (SwiftLint extra) rules.

The print command is useful, but is easy to forget to delete it (after use) from the code base. Now imagine 100 “lost” prints on the code base and you’ll end up with your Xcode console flooded of (printed) messages that you don’t know were they are generated from, and became just noise.

no_print:
included: “.*\\.swift”
name: “Fordidden print”
regex: “print[(]”
message: “Use DevTools.Log…”
severity: warning

Why use let _ = to safely unwrap an option value if we are not using it?

no_letUnderscore:
included: ".*\\.swift"
name: "No let _ = ..."
regex: 'let[ ][_][ ][=]'
message: "Don't use let _ = xxx , use xxx != nil"
severity: error

Hardcoded numbers all over the place are never good thing and one day will backfire, it always does. These kind of “copy-paste” behaviour should be centralised, and if one day that 1000 that we repeat all over the code needs to be a 900, we just need to change on one place.

numbers_smell:
regex: '(return |case |\w\(|: |\?\? |\, |== |<=? |>=? |\+= |\-= |\/= |\*= |%= |\w\.\w+ = )\(*-?\d{2,}'
message: "Numbers smell; define a constant instead."
severity: warning

If it’s commented, does it really needs to be there?

commented_code:
regex: '(?<!:|\/)\/\/\h*[a-z.](?!wiftlint)'
message: "Comment starting with lowercase letter - did you forget to delete old code?"
severity: warning

Some people like to name a singleton varshared, other people like instance and so on. That wont help when some writes MyClass. and then have to scroll on the Xcode auto-complete options to find the desired Singleton var.

naming_Singletons:
included: “.*\\.swift”
name: “Singleton naming”
regex: “static (var|let)[ ](instance|sharedInstance)[ ]*[:]”
message: “Use shared”
severity: error

This principle can of course be applied not only for Singletons.

Other dangerous thing on code are hardcoded timezones or date formats. We can throw a compile error, at the same time we say where to find what we need to use.

no_hardCodedTimeZones:
included: “.*\\.swift”
name: “Fordiden hardcoded TimeZones”
regex: “\”UTC\”|\”GMT\””
message: “Use AppConstants.TimeZones”
severity: error
no_hardCodedDateFormats:
included: ".*\\.swift"
name: "Hardcoded DateFormats"
regex: '= "yyyy|DateFormatter(withFormat'
message: "Use AppContants.DateFormatterTypes"
severity: error

IV — Final considerations.

The rules we can have are endless and will always depend or the project/team. The most important thing here is to know that just 1 rule will always be better than no rules at all, and the more rules we have:

  • The more strong, coherent and consistent our code base will be.
  • The more easy is to ensure a the use of a specific Design Language.
  • The more developers will code using the same style.
  • The more easy will be to find things of the code.

V — Materials.

The yml I use as start point on new projects is bellow. Feel free to use/edit.

My SwiftLint basic template (always change depending of the project needs)

V — Related articles

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store