Swift闭包 - 强制闭包始终完成

时间:2017-08-29 17:07:17

标签: swift closures

是否可以强制关闭完成?与返回值必须始终返回的函数一样,如果有一种方法可以强制闭包包含始终完成所需的语法,那么它将是ace。

例如,此代码将无法编译,因为该函数并不总是返回值:

func isTheEarthFlat(withUserIQ userIQ: Int) -> Bool {
    if userIQ > 10 {
        return false
    }
}

以完全相同的方式,我想定义一个带闭包的函数,如果闭包永远不会返回也不会编译。例如,下面的代码可能永远不会返回completionHandler:

func isTheEarthFlat(withUserIQ userIQ: Int, completionHandler: (Bool) -> Void) {
    if userIQ > 10 {
        completionHandler(false)
    }
}

上面的代码编译,但我想知道是否有一个关键字强制关闭在所有情况下发送完成处理程序。也许它与上述函数中的Void有关?

3 个答案:

答案 0 :(得分:2)

不,如果您忘记(或不需要)在return语句等所有可能条件下调用完成处理程序,则不会导致编译器错误。

这是一个有趣的想法,可能会对语言进行有用的增强。可能在参数声明中的某处作为required关键字。

答案 1 :(得分:2)

您没有特别的关键字。但是有一种有趣的方法可以考虑,不会编译:

func isTheEarthFlat(withUserIQ userIQ: Int, completionHandler: (Bool) -> Void) {
    let result: Bool
    defer {
       completionHandler(result)
    }
    if userIQ > 10 {
        result = false
    }
}

将会被强制调用:

completionHandler

不确定它是一个好用的模式。

答案 2 :(得分:2)

这是我想到的一种有趣的技巧。您可以定义GuarenteedExecutionGuarenteedExecutionResult类型。

GuarenteedExecution是一个闭包的包装器,它将在必须保证闭包执行的上下文中使用。

GuarenteedExecutionResult是执行GuarenteedExecution的结果。诀窍是具有所需的功能,例如isTheEarthFlat,返回GuarenteedExecutionResult。获取GuarenteedExecutionResult实例的唯一方法是在execute(argument:)上调用GuarenteedExecution。实际上,类型检查器功能负责保证返回,现在用于保证GuarenteedExecution的执行。

struct GuarenteedExecutionResult<R> {
    let result: R

    fileprivate init(result: R) { self.result = result }
}

struct GuarenteedExecution<A, R> {
    typealias Closure = (A) -> R

    let closure: Closure

    init(ofClosure closure: @escaping Closure) {
        self.closure = closure
    }

    func execute(argument: A) -> GuarenteedExecutionResult<R> {
        let result = closure(argument)
        return GuarenteedExecutionResult(result: result)
    }
}

单独文件中的示例用法(以便无法访问GuarenteedExecutionResult.init):

let guarenteedExecutionClosure = GuarenteedExecution(ofClosure: {
    print("This must be called!")
})

func doSomething(guarenteedCallback: GuarenteedExecution<(), ()>)
    -> GuarenteedExecutionResult<()> {
    print("Did something")
    return guarenteedCallback.execute(argument: ())
}

_ = doSomething(guarenteedCallback: guarenteedExecutionClosure)