Callback function syntax in Swift
Data Structures & Algorithms practice on Codemia
Step through 300+ coding interview problems with animated visualisers that show the data structure changing as the code runs. The Blind 75 are free.
Introduction
In Swift, what most people call a callback is usually a closure passed into a function. Understanding the syntax matters because the same feature shows up in completion handlers, asynchronous APIs, error handling, animation blocks, and many other parts of Swift code.
The Basic Closure Type
A callback that takes no arguments and returns nothing has this type:
A function can accept it like this:
This is the simplest form of callback syntax in Swift.
Callbacks with Parameters
Most real callbacks pass information back to the caller.
The closure type here is:
That means the callback receives a String and returns nothing.
Callbacks with Success and Failure Information
A common older Swift pattern is to pass optional result and optional error values into a completion handler.
This works, but modern Swift usually prefers Result because it is clearer.
Prefer Result for Typed Outcomes
This makes the contract explicit: the callback returns either a success value or a failure value, but not both at once.
Mark Escaping Closures Correctly
If the callback is stored or called after the function returns, Swift requires @escaping.
Without @escaping, the compiler assumes the closure is used only during the function call itself.
Trailing Closure Syntax
Swift supports trailing closures when the final argument is a closure. That is why callbacks often look like this:
instead of this:
Both are valid. The first is just more idiomatic when the closure is the last argument.
Async and Await Reduce Callback Noise
Modern Swift increasingly replaces callback-heavy APIs with async and await.
Even so, callback syntax still matters because many Apple and third-party APIs still use closures, and async code is often built on top of them.
Avoid Retain Cycles in Stored Callbacks
If a closure captures self and is retained by self, you can create a retain cycle. In those cases use a capture list.
This is not specific to callbacks, but callback-based designs hit this issue often enough that it belongs in the syntax discussion.
Common Pitfalls
The most common mistake is forgetting @escaping when the callback runs later. The compiler will usually catch this, but the reason matters.
Another issue is using the older optional-value plus optional-error pattern when Result would express the contract more clearly.
A third problem is misunderstanding trailing closure syntax and thinking it changes the meaning of the callback. It does not. It only changes how the call is written.
Summary
- In Swift, callbacks are usually closures passed as function parameters.
- A simple callback type looks like
() -> Voidor(Value) -> Void. - Use
@escapingwhen the callback outlives the function call. - Prefer
Resultover parallel optional success and error parameters. - Learn trailing closure syntax because it is the common style in Swift APIs.
Related reading
- Calling a phone number in swift
- Calling a phone number in swift
- Calling setCompoundDrawables doesn't display the Compound Drawable
- Calling startActivity from outside of an Activity?
- Calling startActivity from outside of an Activity context
- Can an Android Toast be longer than Toast.LENGTH_LONG?
- Can I access the App Store from within the iOS Simulator?
- Can I change multiplier property for NSLayoutConstraint?
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseNo course covers this one yet
Basis Lab writes one for you from a sentence about what you want to be able to do, then teaches it and checks you understood. Your first course is free.
Build my courseData Structures & Algorithms practice on Codemia
Step through 300+ coding interview problems with animated visualisers that show the data structure changing as the code runs. The Blind 75 are free.