Swift package
Weak, strong, and unowned closure captures without repetitive guard boilerplate
Weak captures are correct but repetitive. Capture packages the familiar weak-self guard while preserving callback arguments, return values, throwing and async effects, sendability, and actor isolation.
api.fetch { [weak self] response, items, error in
guard let self else { return }
self.handle(
response: response,
items: items,
error: error
)
}
api.fetch(completion: capture {
_self, response, items, error in
_self.handle(
response: response,
items: items,
error: error
)
})
Variadic generics support any callback arity. A Void or optional result needs no fallback; non-optional results make the fallback explicit.
dataSource.numberOfItems = capture(
orReturn: 0,
in: \.items.count
)
Weak is the default. Choose .strong only when ownership is intentional, and .unowned only when invocation after deallocation is a programmer error.
let update = object.capture
.uncheckedSendable
.onMainActor { capturedObject in
capturedObject.updateUI()
}
For stored reference state, the package also provides @Weak, @Strong, @Unowned, and strategy-selected @Captured wrappers.
| Surface | Use it when |
|---|---|
capture { ... } | A Void or optional-returning callback may skip after release |
capture(orReturn:in:) | A non-optional callback needs an explicit fallback |
.as(.strong) / .as(.unowned) | Lifetime semantics intentionally differ from weak |
.onMainActor | The produced closure must preserve main-actor isolation |
.uncheckedSendable | A manually audited callback must cross concurrency boundaries |
Custom reference types can conform to CapturableObjectProtocol; NSObject subclasses already receive the instance capture surface.