What is a Closure?
Closures are self-contained blocks of functionality that can be passed around and used in your code. They can 'capture' and store references to variables and constants from the context in which they are defined. In Swift, functions are actually a special case of closures. As an Architect, you'll use closures primarily for completion handlers (callbacks) and functional programming patterns like map and filter.
- Closure Expression Syntax
Swift closures have a distinct syntax: { (parameters) -> return type in statements }. The in keyword is crucial as it separates the definition of the closure's parameters and return type from its body.
- Trailing Closure Syntax
If a closure is the final argument to a function, Swift allows you to 'pop' it out of the parentheses. This makes the code look much cleaner and more like a standard block of code, which is a common pattern in SwiftUI.
- Escaping Closures (@escaping)
By default, closures are 'non-escaping,' meaning they are executed within the function they are passed to. If a closure needs to be stored and executed after the function returns (like a network request callback), you must mark it as @escaping. This is a vital safety feature that helps the compiler manage memory.
- Memory Management: Capture Lists
Closures can cause Strong Reference Cycles (Memory Leaks) because they hold onto the objects they use. To prevent this, Architects use 'Capture Lists' to define how the closure should interact with the surrounding scope, usually by marking self as weak or unowned.