当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


Swift withoutActuallyEscaping(_:do:)用法及代码示例


函数

withoutActuallyEscaping(_:do:)

允许临时使用非转义闭包,就好像它被允许逃逸一样。

声明

func withoutActuallyEscaping<ClosureType, ResultType>(
    _ closure: ClosureType,
    do body: (ClosureType) throws -> ResultType
) rethrows -> ResultType

返回值

body 闭包的返回值(如果有)。

参数

closure

body 闭包执行期间可转义的非转义闭包值。如果body 有返回值,则该值也用作withoutActuallyEscaping(_:do:) 函数的返回值。

body

使用 closure 的可逃避副本作为其参数立即执行的闭包。

详述

您可以使用此函数调用一个 API,该 API 以一种不允许闭包在实践中转义的方式采用转义闭包。下面的示例演示了如何将 withoutActuallyEscaping(_:do:) 与使用转义闭包的两个常见 API 结合使用:惰性集合视图和异步操作。

以下代码声明了一个 allValues(in:match:) 函数,用于检查数组中的所有元素是否与谓词匹配。该函数不会像编写的那样编译,因为惰性集合的 filter(_:) 方法需要转义闭包。惰性集合不会持久化,因此 predicate 闭包实际上不会转义函数体;但是,它不能以这种方式使用。


func allValues(in array: [Int], match predicate: (Int) -> Bool) -> Bool {
    return array.lazy.filter { !predicate($0) }.isEmpty
}
// error: closure use of non-escaping parameter 'predicate'...

withoutActuallyEscaping(_:do:) 提供了 predicate 的临时可逃逸副本,can 可用于调用惰性视图的 filter(_:) 方法。 allValues(in:match:) 的第二个版本编译没有错误,编译器保证 escapablePredicate 闭包不会持续超过对 withoutActuallyEscaping(_:do:) 的调用。


func allValues(in array: [Int], match predicate: (Int) -> Bool) -> Bool {
    return withoutActuallyEscaping(predicate) { escapablePredicate in
        array.lazy.filter { !escapablePredicate($0) }.isEmpty
    }
}

异步调用是另一种类型的 API,通常会转义其闭包参数。以下代码声明了一个perform(_:simultaneouslyWith:) 函数,该函数使用调度队列同时执行两个闭包。


func perform(_ f: () -> Void, simultaneouslyWith g: () -> Void) {
    let queue = DispatchQueue(label: "perform", attributes: .concurrent)
    queue.async(execute: f)
    queue.async(execute: g)
    queue.sync(flags: .barrier) {}
}
// error: passing non-escaping parameter 'f'...
// error: passing non-escaping parameter 'g'...

perform(_:simultaneouslyWith:) 函数以使用.barrier 标志调用sync(flags:execute:) 方法结束,这会强制函数等到两个闭包都完成运行后再返回。尽管屏障保证两个闭包都不会逃逸函数,但 async(execute:) 方法仍然要求传递的闭包标记为 @escaping ,因此函数的第一个版本无法编译。要解决这些错误,您可以使用 withoutActuallyEscaping(_:do:) 获取可以传递给 async(execute:)fg 的副本。


func perform(_ f: () -> Void, simultaneouslyWith g: () -> Void) {
    withoutActuallyEscaping(f) { escapableF in
        withoutActuallyEscaping(g) { escapableG in
            let queue = DispatchQueue(label: "perform", attributes: .concurrent)
            queue.async(execute: escapableF)
            queue.async(execute: escapableG)
            queue.sync(flags: .barrier) {}
        }
    }
}

可用版本

iOS 8.0+, iPadOS 8.0+, macOS 10.10+, Mac Catalyst 13.0+, tvOS 9.0+, watchOS 2.0+

相关用法


注:本文由纯净天空筛选整理自apple.com大神的英文原创作品 withoutActuallyEscaping(_:do:)。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。