Chapter 84: Swift self Keyword

1. What does self really mean? (the clearest possible explanation)

self is the current instance — the specific object that is currently executing the code.

Think of it as the object answering the phone when one of its own methods is called.

Real-life analogy:

Imagine a classroom full of students. Each student is an instance of the “Person” class.

When the teacher says: “Everyone, please say your own name out loud”

Each student says their own name — not someone else’s.

In code, when a method runs, self is the student who is currently speaking.

Swift

So:

  • self = whoever is currently executing this method
  • Every time a method runs, Swift automatically sets self to the current instance

2. The three main situations where you see self

Swift has very clear rules — once you understand them, self stops being confusing.

Situation 1 — You must write self when there is name conflict

This is the most common reason you see self..

Swift

Rule #1:

You must write self. when the property name and a parameter / local variable have the same name.

This is by far the most frequent place you will type self.

Situation 2 — You must write self inside closures that capture self

Closures capture variables — and when they capture self, you usually need to write it explicitly (especially with [weak self]).

Swift

Rule #2:

Inside closures, you almost always write self. (and usually use [weak self] or [unowned self] to avoid retain cycles)

Situation 3 — You can write self for clarity — even when not required

In many places Swift lets you omit self., but many teams still write it for readability.

Swift

Rule #3:

You may write self. even when Swift doesn’t require it — many style guides recommend it for clarity, especially:

  • in longer methods
  • when mixing local variables and properties
  • in team projects

4. Real-life examples — where you will actually write self

Example 1 – Constructor / initializer (most common place for self)

Swift

Almost every initializer with parameters matching property names uses self.

Example 2 – Method with parameter name conflict

Swift

Example 3 – Closure capturing self (very frequent in networking, UI, timers)

Swift

Very important modern habit:

Always use [weak self] (or [unowned self]) in closures that capture self → prevents memory leaks (retain cycles)

5. When Swift lets you omit self. (and when teams still write it)

You can omit self. in these cases:

  • No name conflict with parameters or local variables
  • Not inside a closure
Swift

But many teams still write self. everywhere:

Swift

Why?

  • Makes it immediately clear that you are accessing a property (not a local variable)
  • Easier to search/refactor
  • Consistent style in large codebases

6. Very Common Beginner Mistakes & Correct Habits

Mistake Wrong / Risky code Correct / Better habit Why?
Forgetting self in initializer init(name: String) { name = name } self.name = name Name conflict — compile error without self
Force-unwrapping self in closures { self.doSomething() } without capture list { [weak self] in self?.doSomething() } Retain cycle / memory leak
Using var self in closures [self] in self.count += 1 [weak self] or [unowned self] Strong reference cycle
Writing self when not needed (but inconsistently) sometimes self.count, sometimes count Decide team style: either always or never Consistency improves readability
Thinking self is optional everywhere self omitted in closures Always explicit in closures Capture list requires clarity

7. Quick Summary — When you must write self

Situation Must write self? Example Reason
Name conflict (parameter or local var) Yes init(name: String) { self.name = name } Compiler requires it
Inside a closure that captures self Yes (usually) { [weak self] in self?.count += 1 } Capture list + safety
Accessing property in computed property/setter Usually yes var fullName: String { self.first + ” ” + self.last } Clarity — many teams always write it
No name conflict, not in closure Optional count += 1 or self.count += 1 Style choice — many teams prefer self.

8. Small Practice — Try these

  1. Create a Person class with:
    • let name: String
    • var age: Int
    • initializer that sets both
    • method introduce() that uses self.name and self.age
  2. Create a Counter class with:
    • var count: Int = 0
    • method increment(by step: Int = 1) that uses self.count
  3. Create a class that uses a closure (Timer or DispatchQueue) and correctly captures [weak self]

Paste your code here if you want feedback or want to see more polished versions!

What would you like to explore next?

  • self in closures — [weak self], [unowned self], capture lists
  • self vs Self (static vs instance context)
  • mutating self in structs vs classes
  • self in SwiftUI (ObservableObject, @StateObject…)
  • Or move to another topic (optionals, arrays, closures, switch…)

Just tell me — we’ll continue in the same clear, detailed, patient style 😊

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *