- August 28, 2025
- Mins Read
When the last parameter to a function is a closure, you can write that closure after the function’s parentheses—without the parameter label. This is called a trailing closure.
func performTask(times: Int, task: () -> Void) {
for _ in 1...times {
task()
}
}
// Call without trailing closure:
performTask(times: 3, task: {
print("Hello")
})
// Trailing closure goes outside the (…):
performTask(times: 3) {
print("Hello")
}
This reads more naturally when the closure is the main “action” you’re passing in.
Swift can infer parameter types and return types from context, and you can:
return
keyword when the body is a single expression.$0
, $1
, …) for positional parameters.let numbers = [1, 2, 3, 4, 5]
// Full form:
let doubledFull = numbers.map { (n: Int) -> Int in
return n * 2
}
// Inferred types + implicit return:
let doubledInferred = numbers.map { n in
n * 2
}
// Shorthand argument name:
let doubledShorthand = numbers.map { $0 * 2 }
UIView.animate { … }
).UIView.animate(withDuration: 0.3) {
view.alpha = 0
}
$0
, $1
, etc. is obvious.map
, filter
, sorted(by:)
, where brevity improves readability.Avoid shorthand when the closure body is complex, when you have more than 2–3 parameters, or when semantic names (from
, to
, value
) would clarify intent.
Paste this into a playground to verify you can use $0
, $1
correctly:
// Test array of strings, sort by length using shorthand:
let words = ["swift", "closure", "trailing", "syntax"]
let sortedByLength = words.sorted { $0.count < $1.count }
assert(sortedByLength == ["swift", "syntax", "closure", "trailing"])
print("Test Passed: sortedByLength == \(sortedByLength)")
// Test mapping to optionals via shorthand:
let raw = ["1", "two", "3", "4a"]
let ints = raw.compactMap { Int($0) }
assert(ints == [1, 3])
print("Test Passed: ints == \(ints)")
Test Passed: sortedByLength == ["swift", "syntax", "closure", "trailing"]
Test Passed: ints == [1, 3]
In Swift you can pass functions or closures into other functions by specifying a function type as a parameter. The syntax is:
func performOperation(_ a: Int, _ b: Int, operation: (Int, Int) -> Int) {
let result = operation(a, b)
print("Result is \(result)")
}
Here, operation
is a parameter whose type is a closure taking two Int
s and returning an Int
.
func add(_ x: Int, _ y: Int) -> Int {
return x + y
}
performOperation(4, 5, operation: add)
// Prints: Result is 9
performOperation(4, 5, operation: { (x, y) in
x * y
})
// Prints: Result is 20
If the last (or only) parameter is a closure, you can write it after the function call’s parentheses:
performOperation(4, 5) { x, y in
x - y
}
// Prints: Result is -1
// Define a function that applies a closure twice
func applyTwice(to value: Int, using transform: (Int) -> Int) -> Int {
return transform(transform(value))
}
// Test with a doubling closure
let double = { (x: Int) -> Int in x * 2 }
let result1 = applyTwice(to: 3, using: double)
assert(result1 == 12)
print("Test 4.1 Passed: applyTwice doubled twice == \(result1)")
Expected output:
Test 4.1 Passed: applyTwice doubled twice == 12
// Reuse applyTwice but with a trailing closure that adds 5
let result2 = applyTwice(to: 10) { $0 + 5 }
assert(result2 == 20)
print("Test 4.2 Passed: applyTwice with +5 twice == \(result2)")
Expected output:
Test 4.2 Passed: applyTwice with +5 twice == 20
With these patterns you can accept, customize, and test functions/closures passed into your Swift APIs. Feel free to extend these examples to more parameters, different return types, or even throwing closures!
This package provides you with an easy way to show tooltips over any SwiftUI view, since Apple does not provide ...
SimpleToast is a simple, lightweight, flexible and easy to use library to show toasts / popup notifications inside iOS or ...
Create Toast Views with Minimal Effort in SwiftUI Using SSToastMessage. SSToastMessage enables you to effortlessly add toast notifications, alerts, and ...