Allows a nonescaping closure to temporarily be used as if it were
allowed to escape.
This is useful when you need to pass a closure to an API that can't
statically guarantee the closure won't escape when used in a way that
won't allow it to escape in practice, such as in a lazy collection
view:
func allValues(in array: [Int], matchPredicate: (Int) -> Bool) -> Bool {
// Error because `lazy.filter` may escape the closure if the `lazy`
// collection is persisted; however, in this case, we discard the
// lazy collection immediately before returning.
return array.lazy.filter { !matchPredicate($0) }.isEmpty
}
or with async:
func perform(_ f: () -> Void, simultaneouslyWith g: () -> Void,
on queue: DispatchQueue) {
// Error: `async` normally escapes the closure, but in this case
// we explicitly barrier before the closure would escape
queue.async(f)
queue.async(g)
queue.sync(flags: .barrier) {}
}
withoutActuallyEscaping provides a temporarily-escapable copy of the
closure that can be used in these situations:
closure: A non-escaping closure value that will be made
escapable for the duration of the execution of the do block.
do: A code block that will be immediately executed, receiving
an escapable copy of closure as an argument.
Returns: the forwarded return value from the do block.
Remark: It is undefined behavior for the escapable closure to be stored,
referenced, or executed after withoutActuallyEscaping returns. A
future version of Swift will introduce a dynamic check to trap if
the escapable closure is still referenced at the point
withoutActuallyEscaping returns.
Allows a nonescaping closure to temporarily be used as if it were allowed to escape.
This is useful when you need to pass a closure to an API that can't statically guarantee the closure won't escape when used in a way that won't allow it to escape in practice, such as in a lazy collection view:
func allValues(in array: [Int], matchPredicate: (Int) -> Bool) -> Bool { // Error because `lazy.filter` may escape the closure if the `lazy` // collection is persisted; however, in this case, we discard the // lazy collection immediately before returning. return array.lazy.filter { !matchPredicate($0) }.isEmpty }
or with
async
:func perform(_ f: () -> Void, simultaneouslyWith g: () -> Void, on queue: DispatchQueue) { // Error: `async` normally escapes the closure, but in this case // we explicitly barrier before the closure would escape queue.async(f) queue.async(g) queue.sync(flags: .barrier) {} }
withoutActuallyEscaping
provides a temporarily-escapable copy of the closure that can be used in these situations:` func allValues(in array: [Int], matchPredicate: (Int) -> Bool) -> Bool { return withoutActuallyEscaping(matchPredicate) { escapablePredicate in array.lazy.filter { !escapableMatchPredicate($0) }.isEmpty } }
func perform(_ f: () -> Void, simultaneouslyWith g: () -> Void, on queue: DispatchQueue) { withoutActuallyEscaping(f) { escapableF in withoutActuallyEscaping(g) { escapableG in queue.async(escapableF) queue.async(escapableG) queue.sync(flags: .barrier) {} } } }
`
closure
: A non-escaping closure value that will be made escapable for the duration of the execution of thedo
block.do
: A code block that will be immediately executed, receiving an escapable copy ofclosure
as an argument. Returns: the forwarded return value from thedo
block. Remark: It is undefined behavior for the escapable closure to be stored, referenced, or executed afterwithoutActuallyEscaping
returns. A future version of Swift will introduce a dynamic check to trap if the escapable closure is still referenced at the pointwithoutActuallyEscaping
returns.Declaration
func
withoutActuallyEscaping
<
ClosureType
,
ResultType
>
(
_
closure
:
ClosureType
,
do
: (
ClosureType
)
throws
-
>
ResultType
)
rethrows
-
>
ResultType