How to create and use closures?
  • July 29, 2025

1. What Is a Closure (and Why Swift Loves Them)

A closure in Swift is a self-contained block of functionality that you can pass around and use in your code. Closures can:

  • Capture and store references to constants and variables from the context where they’re defined (“closing over” them).
  • Be assigned to variables, passed as arguments to functions, and returned from functions.
  • Let you write very concise, on-the-fly pieces of executable code—perfect for callbacks, event handling, array transformations, and more.

Swift uses closures everywhere:

  • Completion handlers (URLSession.shared.dataTask { … })
  • Functional APIs (map, filter, reduce)
  • Custom asynchronous or reactive patterns

Because they’re so flexible and lightweight, closures let you express complex behavior inline, without the ceremony of defining a named function.


2. Closure Syntax Basics

A closure’s full form looks a lot like a function:

{ (parameters) -> ReturnType in
    // body
}
  • Curly braces { … } denote the closure.
  • Parameters are declared in parentheses, just like a function.
  • -> ReturnType tells what it returns.
  • The in keyword separates the signature from the body.

Example: Simple Closure

let sayHello = { 
    print("Hello, world!") 
}
sayHello()  // prints "Hello, world!"

3. Why Are Closure Parameters Inside Braces?

Unlike function declarations, closures are expressions, so their parameter list and return type must live entirely inside the {}. There’s no separate signature line:

// Function declaration
func add(a: Int, b: Int) -> Int { return a + b }

// Closure expression
let addClosure = { (a: Int, b: Int) -> Int in
    return a + b
}

Putting everything inside {} keeps closures self-contained and emphasizes that you’re creating a first-class value, not defining a top-level function.


4. Shorthand & Inferencing

Swift can infer parameter types and return types, and even let you use shorthand argument names. That’s why you often see:

// Full form
let sumFull = { (a: Int, b: Int) -> Int in
    return a + b
}

// Inferred form
let sumInferred: (Int, Int) -> Int = { a, b in
    a + b       // implicit return
}

// Shorthand argument names
let sumShorthand: (Int, Int) -> Int = { $0 + $1 }

5. Returning a Value from a No-Parameter Closure

If your closure takes no parameters but returns something, you still use the -> Type in syntax and a return (or implicit return for single expressions):

let randomBool: () -> Bool = {
    return Bool.random()
}

// Or shorthand (single expression):
let randomShorthand: () -> Bool = {
    Bool.random()
}

// Call it
let value = randomBool()

6. Tests

Below are small “tests” you can paste into a Swift playground or project to verify your understanding of closures.

6.1 Creating a Basic Closure

// Test 1: No parameters, no return
let greet: () -> Void = {
    print("Test 1 Passed: Hello from closure!")
}
greet()

Expected output:
Test 1 Passed: Hello from closure!


6.2 Accepting Parameters in a Closure

// Test 2: Parameters, no return
let repeatPrint: (String, Int) -> Void = { message, count in
    for _ in 1...count {
        print(message)
    }
}
print("Test 2 Output:")
repeatPrint("Swift", 3)

Expected output:

Test 2 Output:
Swift
Swift
Swift

6.3 Returning Values from a Closure

// Test 3a: Return an Int
let multiply: (Int, Int) -> Int = { a, b in
    return a * b
}
assert(multiply(4, 5) == 20)
print("Test 3a Passed: 4 * 5 == \(multiply(4, 5))")

// Test 3b: No parameters, return Bool
let isEven: (Int) -> Bool = { $0 % 2 == 0 }
assert(isEven(42) == true)
print("Test 3b Passed: 42 is even? \(isEven(42))")

7. Summary

  • Closures are inline, anonymous functions you pass around.
  • They use { (params) -> ReturnType in … } syntax entirely inside braces.
  • Swift infers types and lets you use shorthand ({ $0 + $1 }).
  • To return a value from a no-param closure, declare () -> Type and use return (or implicit for single expressions).
  • You can verify your understanding with the simple tests above.
YOU MIGHT ALSO LIKE...
PermissionsSwiftUI: A SwiftUI package to handle permissions

PermissionsSwiftUI displays and handles permissions in SwiftUI. It is largely inspired by SPPermissions. The UI is highly customizable and resembles an Apple style. ...

Pager tab strip view

Introduction PagerTabStripView is the first pager view built in pure SwiftUI. It provides a component to create interactive pager views ...

PageView

SwiftUI view enabling page-based navigation, imitating the behaviour of UIPageViewController in iOS.

Pages

    

How to take action when a property changes

1. Taking Action When a Property Changes: Property Observers Swift lets you observe and respond to changes in a property’s ...