When to write `self` in Swift

Or must the dinosaurs die?

Oleksii Huralnyk
The Startup
4 min readFeb 2, 2021

--

The other day I encountered on “you forgot to put self before property” comment in my pull request. Did I? Or it’s actually better to omit unnecessary self? Let's try to figure out.

One of the really shining sides of the Swift is its brevity. The developer could write really compact code omitting a lot of boiler-plate thanks to type inference, synthesized conformance to standard protocols (e.g. Codable, Equatable), trailing closure syntax, you can continue this list if you want. But as uncle Ben said: “with great power comes great responsibility” or Swift API Design Guidelines say: “clarity is more important than brevity”, so don’t overuse these little features.

Reasons to write self

Indeed, the main reason to put self when compiler lets you omit self is it should be clear whether a piece of code accessing instance variable or local variable.

For example, we see such a piece of code:

Somewhere deep in mind we understand that cache and fetchEvents are instance variable and method, but we not 100% sure. It because Medium doesn’t support syntax highlighting. When you would see same code in your favorite IDE it would be something like this:

All your doubts are gone.

When we prepend all instance variables and methods with self we would solve the problem for environments without syntax highlighting such as GitHub, Medium, name it.

So, to omit self makes it harder to reason about code for color blinded people and when you’re reading code outside IDE.

But there is another reason to put self on every corner: when you’re dinosaur with huge baggage of Objective-C experience and can’t accept rules of new game. Or you’re really lazy and you’ve already been taught some weird guidelines.

There was even Swift evolution proposal SE-0009 to make self required but it was rejected. Let’s think why.

Reasons not to write self

I can count two reasons when the Swift compiler forces developer to put self before instance variables.

  • to avoid ambiguity, for example in initializers
  • to avoid accidentally create a strong reference cycle in escaping closure

With first reason all crystal clear, take a look at this snippet:

Indeed, compiler should distinguish which name is local and which is instance variable.

Second reason has a special consideration in Swift Docs, I hope you read them, if no go to do it right now.

An escaping closure that refers to self needs special consideration if self refers to an instance of a class. Capturing self in an escaping closure makes it easy to accidentally create a strong reference cycle.

Normally, a closure captures variables implicitly by using them in the body of the closure, but in this case you need to be explicit. Writing self explicitly lets you express your intent, and reminds you to confirm that there isn’t a reference cycle.

Previously self needed special consideration in all escaping closures but in Swift 5.3 includes changes SE-0269 to increase availability of implicit selfin escaping closures when reference cycles are unlikely to occur. And now compiler would give you an error only when self refers to an instance of a class.

If you’re making a habit to spread self all over the place you are making yourself blind and all attempts of guys from Cupertino to make your life easier go to hell.

I’ve asked several developers at Twitter whether they write self where they don’t have to. Most of them write self as little as possible, one of them event punish his teammates for overuse of self. Only one responded that he used to write it everywhere, cause it makes code review easier.

Let’s summarize.

We put self everywhere if doctor tells you so, if it helps you to conduct a code review or if you’re an ignorant dinosaur.

We put self as little as possible if we want to make code compact, reduce amount of cognitive load, virtually to reduce time to write code, and mostly to help compiler to save you from accidental mistakes.

Thanks to make it till the end. I’m curious what do you think about this and what your team practice, don’t be shy to leave the comment.

--

--