1

I am trying out to figure out how does capturing in Swift closures work.

Let's assume the following code example

class Worker {
    let block: () -> Void
    let id: String

    init(id: String, block: @escaping  () -> Void) {
        self.id = id
        self.block = block
    }
}

var worker: Worker!

worker = Worker(id: "1", block: { _ in
    print(worker.id)
})

At the moment the closure is being created, the worker variable is still nil. However, the closure will successfully capture the worker variable.

How does that work? How does the closure keep a strong reference to a variable that still not being initialized?

itskoBits
  • 435
  • 4
  • 13
  • 1
    Compare https://stackoverflow.com/q/43171341/2976878 – Hamish Oct 06 '17 at 14:08
  • 1
    Note that `worker` *is* initialised in your example, it is implicitly initialised to `nil` (and then you *assign* it a reference to a new `Worker` instance). – Hamish Oct 06 '17 at 14:14
  • The worker is in fact initialized, but at a later point. At the moment the closure is created, the worker is still nil. – itskoBits Oct 06 '17 at 14:33
  • 1
    My point is that being `nil` *is* initialised. `nil` and uninitialised are two completely different states. For one, you cannot capture a variable before it has been initialised (try `var i: Int; let c = { i += 1 }`). – Hamish Oct 06 '17 at 14:33
  • You are correct, the variable gets initialized with nil. – itskoBits Oct 06 '17 at 15:01

1 Answers1

0

Closures in Swift capture all variables by reference, just like how variables declared as __block are captured by blocks in Objective-C. Therefore, changes to the variable outside the closure after the closure is created are still seen in the closure when it runs.

newacct
  • 119,665
  • 29
  • 163
  • 224