Closures in Depth

Closures are blocks of code you can pass around like values. This lesson covers full and shorthand syntax, trailing closures , capturing values, and the difference between escaping and non-escaping closures — the foundation of callbacks and functional Swift.

Learn Closures in Depth in our free Swift course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.

Part of the free Swift course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

What You'll Learn in This Lesson

1️⃣ Closure Syntax

The full closure form is {' (params) -> ReturnType in body '} . The in keyword separates the signature from the body. A closure can take no parameters and return nothing — its type is then () -> Void .

2️⃣ Trailing Closures

When a closure is the last argument to a function, you can write it after the parentheses. This trailing-closure style is everywhere in Swift and SwiftUI because it reads so cleanly.

3️⃣ Shorthand: $0, Inferred Types & Returns

Swift lets you drop a lot of ceremony. Parameter types can be inferred, a single-expression body needs no return , and $0 / $1 name the arguments positionally.

4️⃣ Capturing Values (and Escaping)

A closure captures variables from the scope where it's defined and keeps them alive. A closure that's stored and called after the function returns is escaping — you mark its parameter @escaping , and using self inside it must be explicit.

Your turn. Fill in the blanks to use shorthand arguments and the in keyword.

📋 Quick Reference

No blanks this time — just a brief and an outline. Build it, run it, and check your output against the example in the comments.

Practice quiz

What is a closure in Swift?

  • A class that can't be subclassed
  • A type of optional
  • A self-contained block of code that can be passed around
  • A protocol requirement

Answer: A self-contained block of code that can be passed around. A closure is a self-contained block of functionality that can be stored, passed, and called later.

What keyword separates a closure's parameters from its body?

  • in
  • return
  • do
  • then

Answer: in. The 'in' keyword separates the parameter/return list from the closure body.

What is a trailing closure?

  • A closure stored in a variable
  • A closure that returns nothing
  • A closure with no parameters
  • A closure written after the call's parentheses when it's the last argument

Answer: A closure written after the call's parentheses when it's the last argument. When a closure is the final argument, you can move it outside the parentheses as a trailing closure.

What does the shorthand argument $0 refer to?

  • The return value
  • The first parameter of the closure
  • The closure itself
  • An optional binding

Answer: The first parameter of the closure. $0 is shorthand for the first parameter, $1 the second, and so on.

What does it mean to 'capture' a value in a closure?

  • To keep a reference to a variable from the surrounding scope
  • To copy it into a struct
  • To make it constant
  • To delete it after use

Answer: To keep a reference to a variable from the surrounding scope. A closure captures variables/constants from its surrounding context and can keep using them.

What is an escaping closure?

  • A closure that throws errors
  • A closure that can't capture values
  • A closure stored and called AFTER the function returns
  • A closure with no body

Answer: A closure stored and called AFTER the function returns. An @escaping closure outlives the function call — it's stored and invoked later, e.g. in a completion handler.

By default, are closure parameters to a function escaping or non-escaping?

  • Escaping
  • Non-escaping
  • Always escaping for async
  • Neither — it must be specified

Answer: Non-escaping. Closure parameters are non-escaping by default; you opt in to escaping with @escaping.

When can you omit a closure's 'return' keyword?

  • Never
  • Only for trailing closures
  • Only when it returns Void
  • When the closure body is a single expression

Answer: When the closure body is a single expression. For a single-expression closure, Swift infers the return, so you can omit 'return'.

Which is a valid empty closure type that takes no parameters and returns nothing?

  • Void -> Int
  • () -> ()
  • (Int)
  • { }

Answer: () -> (). () -> () (or () -> Void) is a closure taking no arguments and returning nothing.

Why might @escaping closures require you to write self explicitly?

  • For performance
  • Because self is optional
  • To make capturing of self visible and avoid accidental retain cycles
  • It is never required

Answer: To make capturing of self visible and avoid accidental retain cycles. Escaping closures that use self require explicit self, making the strong capture (and possible retain cycle) obvious.