You are on page 1of 16

Menu

How to use correctly 'self' keyword


in Swift
Dmitri Pavlutin | 09 Nov 2016

In Swift self is a special property of an instance that holds the instance


itself. Most of the times self appears in an initializer or method of a class,
structure or enumeration.

The motto favor clarity over brevity is a valuable strategy to follow. It applies
e ciently in most of the cases, and helps to increase the code readability,
but... a ects code shortness.

Applying this motto to self, the following 2 opposites arise:

* Should you apply the clarity strategy and keep always self to access
instance properties self.property?
* Or accessing the property from a method brings su cient context to
omit self.property without signi cant readability loss?
The answer is that Swift permits and even encourages you to omit self
Menu
keyword when it can be done. The challenge is to determine the scenarios
when self is obligatory and when optional.

Challenge accepted! Let's dive into an interesting review of self keyword


in Swift.

1. Access instance properties and


methods
For example the following structure Weather uses self in its initializer and
isDayForWalk() method:
Try in Swift sandbox

struct Weather {

let windSpeed: Int // miles per hour


let chanceOfRain: Int // percent

init(windSpeed: Int, chanceOfRain: Int) {


self.windSpeed = windSpeed
self.chanceOfRain = chanceOfRain
}

func isDayForWalk() -> Bool {


let comfortableWindSpeed = 5
let acceptableChanceOfRain = 30
return self.windSpeed <= comfortableWindSpeed
&& self.chanceOfRain <= acceptableChanceOfRain
}

}
// A nice day for a walk
let niceWeather = Weather(windSpeed: 4, chanceOfRain: 25)
print(niceWeather.isDayForWalk()) // => true
self special property inside init(windSpeed:chanceOfRain:) and
isDayForWalk() is the current instance of Weather structure. It allows toMenu
set
and access the structure properties self.windSpeed and
self.chanceOfRain.

The structure looks nice.

Nevertheless accessing every time self property may be excessive. The


structure initializer and method provide enough context: everything
happens inside the structure. Is it possible to get rid of self?

As mentioned in the introduction, Swift encourages you to omit the self


keyword whenever possible.

In the previous example, it is recommended to remove self from


isDayForWalk() method. This makes the method shorter:
Try in Swift sandbox

struct Weather {
/* ... */
func isDayForWalk() -> Bool {
let comfortableWindSpeed = 5
let acceptableChanceOfRain = 30
return windSpeed <= comfortableWindSpeed
&& chanceOfRain <= acceptableChanceOfRain
}
}

Because isDayForWalk() method is always invoked in the context of


Weather's instance, Swift enables access of windSpeed and chanceOfRain
without self.

Inside the initializer init(windSpeed:chanceOfRain:) the parameters and


structure properties have the same names windSpeed and chanceOfRain.
Contrary to previous case, now you cannot remove self keyword,
because it would create an ambiguity between the parameter and property
Menu
names.

self helps making an explicit distinction between parameters (windSpeed


and chanceOfRain used without self) and structure properties
(self.windSpeed and self.chanceOfRain, accessed with self).

Let's make an experiment and still remove self from the initializer:
Try in Swift sandbox

struct Weather {
/* ... */
init(windSpeed: Int, chanceOfRain: Int) {
windSpeed = windSpeed
chanceOfRain = chanceOfRain
}
/* ... */
}

Looking at the assignment windSpeed = windSpeed, how Swift can


understand which variable is a parameter and which is a property? It's an
ambiguity, so Swift plainly decides that you mean only the parameters.

As result an error is thrown: cannot assign to value: 'windSpeed' is a


'let' constant. It happens because let constant is assigned to itself
windSpeed = windSpeed, which is not allowed.
Menu

2. To be, or not to be
There were plenty of discussions about the obligatory usage of self to
access properties, or contrary to skip self.

The obligatory usage of self brings the bene ts of consistency and favors
clarity over brevity. You can clearly see the di erence between the instance
properties (that are pre xed with self.) from locally de ned variables.
Maybe...

In my opinion, when you have troubles to distinguish instance properties


from local variables within a method: you have a di erent, deeper problem.

When a structure or class has an excessive number of properties (so called


God object), you're probably breaking the Single responsibility principle.
If a method uses a big number of these properties and declares
correspondingly many local variables, then such method does too many
things. Using an explicit self to distinguish somehow properties from
variables is a temporary workaround for a bad code.
It should not be that way.
Menu

Now imagine a well designed structure or class, which has a single


responsibility. It contains only strictly necessary properties. A well written
method is performing one determined action and as result its code is simple
and obvious.
Surely you don't have the problem to distinguish local variables from
instance properties in such a method. The usage of self may be even
discouraged, since your adding to obvious code redundant explanations.

So design your classes and structures well, and don't let the methods grow
to thousands of lines of code. Then you can omit self without di culties,
and your code becomes even more expressive and concise.

3. Access type properties and methods


self refers to a type (rather than to an instance) when used in a type
method.

Let's de ne following Const structure with type properties minLimit,


maxLimit and type method getLimitRange():
Try in Swift sandbox

struct Const {
static let minLimit = 0
static let maxLimit = 250
static func getLimitRange() -> ClosedRange<Int> {
return self.minLimit...self.maxLimit
}
}
print(Const.getLimitRange()) // => 0...250

Within the type method getLimitRange() the type properties are accessed
using self.minLimit and self.maxLimit. In this case self refers to Const
type directly.
Menu

Interestingly that you can access type properties using two additional
forms.

Firstly you can omit self, and Swift cleverly deduces you're accessing type
properties:
Try in Swift sandbox

struct Const {
static let minLimit = 0
static let maxLimit = 250
static func getLimitRange() -> ClosedRange<Int> {
return minLimit...maxLimit
}
}
print(Const.getLimitRange()) // => 0...250

Secondly you can indicate the type Const explicitly when accessing the
properties:
Try in Swift sandbox

struct Const {
static let minLimit = 0
static let maxLimit = 250
static func getLimitRange() -> ClosedRange<Int> {
return Const.minLimit...Const.maxLimit
}
}
print(Const.getLimitRange()) // => 0...250

Const.minLimit is my personal preference when accessing type properties.


Const serves as a namespace that groups constants.

I nd great that Swift allows 3 ways to access static properties. Use the one
you like!

4. Access instance properties and


4. Access instance properties and Menu
methods in a closure

A closure is a block of code that can be referenced, passed around and


invoked when necessary. A closure has access to variables from the
environment where it was de ned, also called the closure scope.

Sometimes you need to de ne a closure in a method. The closure can access


the local method variables. What's more important you have to explicitly
write self to access instance properties or methods within the closure.

Let's de ne a closure inside a method:


Try in Swift sandbox

class Collection {
var numbers: [Int]

init(from numbers: [Int]) {


self.numbers = numbers
}

func getAppendClosure() -> (Int) -> Void {


return {
self.numbers.append($0)
}
}
}
var primes = Collection(from: [2, 3, 5])
let appendToPrimes = primes.getAppendClosure()
appendToPrimes(7)
appendToPrimes(11)
print(primes.numbers) // => [2, 3, 5, 7, 11]

Collection is a class that holds some prime numbers.


The method getAppendClosure() returns a closure that when invoked
appends a new number to the collection. To access numbers property
within the closure you have to explicitly use self keyword: {
self.numbers.append($0) } .
The explicit use of self in a closure is an intentional design. Because
Menu
closure captures the scope variables, including self reference, you may
create a strong reference cycle between the closure and self. And you
should beware of this potential problem.

To create a strong reference cycle, the common scenario is when a


property of an instance is a closure that captures the instance itself. Let's see
a sample:
Try in Swift sandbox

class Person {
let name: String
lazy var sayMyName: () -> String = {
return self.name
}

init(withName name: String) {


self.name = name
}

deinit {
print("Person deinitialized")
}
}
var leader: Person?
leader = Person(withName: "John Connor")
if let leader = leader {
print(leader.sayMyName())
}
leader = nil

When the variable leader is assigned with nil, normally the instance
should be deinitianilazied. You can expect deinit method to be called that
prints "Person deinitialized" message. However this does not happen.

The strong reference cycle creates the problem.


Menu

The instance holds the closure reference leader.sayMyName and


simultaneously the closure captures and holds the instance reference {
return self.name }. Under such circumstances the reference cycle cannot
be broken and as result both leader instance and the closure cannot be
deallocated.

The solution is to de ne inside the closure a capture list and mark self as
an unowned reference. Let's x the previous example:
Try in Swift sandbox

class Person {
/* ... */
lazy var sayMyName: () -> String = {
[unowned self] in
return self.name
}
/* ... */
deinit {
print("Person deinitialized")
}
}
var leader: Person?
leader = Person(withName: "John Connor")
if let leader = leader {
print(leader.sayMyName())
}
leader = nil
// => "Person deinitialized"
Notice that [unowned self] is added in the closure, which marks self as an
Menu
unowned reference. Now the closure does not keep a strong referenceto
self instance. The strong reference cycle between instance and closure is
no longer created.

Since leader instance is not necessary leader = nil, the memory is


deallocated correctly. The deinitializer deinit is called as expected, which
prints "Person deinitialized" message to the console.

I recommend to read more about instances lifetime at Unowned or Weak?


Lifetime and Performance.

Important. When you access self in a closure, you should always verify
whether a strong reference cycle is not created.

4. Individual self usage


Of course there are plenty of situations when you need to return or modify
self directly. Let's enumerate the common scenarios.

Method chaining
When working with classes, you might want to implement a method
chaining. Such practice is useful to chain multiple method calls on the same
instance, without storing the intermediate results.

The following example is implementing a simple Stack data structure. You


can push or pop elements in the stack. Let's take a look:
Try in Swift sandbox

class Stack<Element> {
fileprivate var elements = [Element]()

@discardableResult
func push(_ element: Element) -> Stack {
elements.append(element) Menu
return self
}

func pop() -> Element? {


return elements.popLast()
}

func printElements() {
print(elements)
}
}
var numbers = Stack<Int>()
numbers
.push(8)
.push(10)
.push(2)
numbers.printElements() // => [8, 10, 2]

The method push(:) returns the current instance self. This enables the
method chaining calls to push multiple elements 8, 10 and 2 at once into the
stack.
Notice that @discardableResult attribute for push(:) method suppresses
the warning that the result of the last method call in the chain is unused.

Enumeration case
To nd what case holds the enumeration within its method, you can easily
query self property with a switch statement.

For example, let's get a string message that describes the enumeration cases:
Try in Swift sandbox

enum Activity {
case sleep
case code
case learn
case procrastinate
func getOccupation() -> String { Menu
switch self {
case .sleep:
return "Sleeping"
case .code:
return "Coding"
case .learn:
return "Reading a book"
default:
return "Enjoying laziness"
}
}
}
let improving = Activity.learn
print(improving.getOccupation()) // => "Reading a book"

The method getOccupation() accesses self to determine the current


enumeration case.

New structure instance


In a structure you can dynamically modify the current instance by
assigning to self a new value:
Try in Swift sandbox

struct Movement {
var speed: Int

mutating func stop() {


self = Movement(speed: 0)
}
}
var run = Movement(speed: 20)
print(run.speed) // => 20
run.stop()
print(run.speed) // => 0
In the mutating method stop() the assignment self = Movement(speed:
Menu
0) modi es the current instance to a new one.

5. Conclusion
self is a property on the instance that refers to itself. It's used to access class,
structure and enumeration instance within methods.

When self is accessed in a type method (static func or class func), it


refers to the actual type (rather than an instance).

Swift allows to omit self when you want to access instances properties. My
advice is to rely on shortness and skip self whenever possible.

When a method parameter have the same name as instance property, you
have to explicitly use self.myVariable = myVariable to make a
distinction.
Notice that method parameters have a priority over instance properties.

Do you think self should be omitted or kept? Feel free to write your opinion in
the comments section below!

swift self

Dmitri Pavlutin
Web developer. JavaScript languages fan. I enjoy coding, blogging,
learning, open sourcing and solving problems. About me

Follow @panzerdp 747 followers


Menu

Popular articles Recent articles


Gentle explanation of 'this' keyword 7 tips to handle unde ned in
in JavaScript JavaScript
How three dots changed JavaScript Announcing Voca: The ultimate
JavaScript string library
Six ways to declare JavaScript
functions Make your Swift code expressive:
addition operator use cases
When 'not' to use arrow functions

Subscribe to our newsletter!


Learning is the key to success: level up your skills with latest articles from
Rainsoft.

email address

Subscribe
Menu
0 Comments Rainsoft 1 Login

Sort by Best
Recommend Share

Start the discussion

LOG IN WITH

OR SIGN UP WITH DISQUS ?

Name

Be the rst to comment.

ALSO ON RAINSOFT

Must know details about ES2016 JavaScript variables hoisting in details


features 12 comments a year ago
8 comments a year ago luckyluckyx x great article !
Gjermund Bjaanes Very good, in-depth
article! Small but good updates to the
standard here, for sure :)

Gentle explanation of 'this' keyword in Catch the XMLHttpRequest in vanilla


JavaScript javascript
51 comments a year ago 1 comment a year ago
Dmitri Pavlutin Separating means that Martin Spierings While you catch the
you don't call the method on an object, code, this doesn't really prevent further

Hosted on Webfaction

You might also like