Professional Documents
Culture Documents
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.
* 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.
struct Weather {
}
// 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.
struct Weather {
/* ... */
func isDayForWalk() -> Bool {
let comfortableWindSpeed = 5
let acceptableChanceOfRain = 30
return windSpeed <= comfortableWindSpeed
&& chanceOfRain <= acceptableChanceOfRain
}
}
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
}
/* ... */
}
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...
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.
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
I nd great that Swift allows 3 ways to access static properties. Use the one
you like!
class Collection {
var numbers: [Int]
class Person {
let name: String
lazy var sayMyName: () -> String = {
return self.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 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.
Important. When you access self in a closure, you should always verify
whether a strong reference cycle is not created.
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.
class Stack<Element> {
fileprivate var elements = [Element]()
@discardableResult
func push(_ element: Element) -> Stack {
elements.append(element) Menu
return self
}
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"
struct Movement {
var speed: Int
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.
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
email address
Subscribe
Menu
0 Comments Rainsoft 1 Login
Sort by Best
Recommend Share
LOG IN WITH
Name
ALSO ON RAINSOFT
Hosted on Webfaction