पाठ 11 / 25

Closures and Capture Lists

Write closures with shorthand syntax, trailing closures and capture lists, and know @escaping.

Functions without names

Closures are self-contained blocks of functionality, like lambdas in other languages: { (a: Int, b: Int) -> Bool in a < b }. Swift lets you shorten them heavily: inferred types, implicit returns, shorthand arguments ($0, $1) and trailing closure syntax when the closure is the last argument (orders.sorted { $0.total > $1.total }), with multiple trailing closures for APIs such as animations. Closures capture variables from their surrounding scope by reference. A closure passed to a function that stores it or calls it later must be marked @escaping by that function, while non-escaping closures (the default) are called before the function returns. Escaping closures that capture self in a class can create retain cycles, so use a capture list such as [weak self] (then guard let self else { return }) or [unowned self] when you are certain of lifetimes. Capture lists can also capture values at creation time: [count] copies the current value instead of referencing the variable.

Closure syntax and capture lists

From full syntax to shorthand, and weak self in an escaping closure.

let prices = [499.0, 120.0, 899.0]

let sortedFull = prices.sorted(by: { (a: Double, b: Double) -> Bool in return a < b })
let sortedShort = prices.sorted { $0 < $1 }          // trailing closure + shorthand
let withTax = prices.map { $0 * 1.18 }

func makeCounter() -> () -> Int {
    var count = 0
    return { count += 1; return count }                 // captures count by reference
}
let next = makeCounter()
_ = next()      // 1
_ = next()      // 2

final class ImageLoader {
    private var cache: [URL: Data] = [:]

    func load(_ url: URL, completion: @escaping (Data?) -> Void) {
        URLSession.shared.dataTask(with: url) { [weak self] data, _, _ in
            guard let self else { return }                   // loader may already be gone
            if let data { self.cache[url] = data }
            completion(data)
        }.resume()
    }
}

A note that remembers the room

A closure is a note written in a room that still remembers the room's contents. If the note is pinned to the room's own wall and the room keeps the note, neither can ever be thrown away: that is a retain cycle, and [weak self] breaks it.

त्वरित जाँच: When must a closure parameter be marked @escaping?

  • Always
  • When the function stores the closure or calls it after returning
  • When the closure returns a value
  • When it uses $0
Answer

When the function stores the closure or calls it after returning — Escaping closures outlive the function call, which affects memory management and capturing.