首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >快速闭包-强制闭包始终完成

快速闭包-强制闭包始终完成
EN

Stack Overflow用户
提问于 2017-08-29 17:07:17
回答 3查看 583关注 0票数 4

是否有可能强制关闭?与具有返回值的函数必须始终返回相同的方式一样,如果有一种方法强制闭包包含始终完成所需的语法,则这将是最好的。

例如,这个代码不会编译,因为函数并不总是返回一个值:

代码语言:javascript
复制
func isTheEarthFlat(withUserIQ userIQ: Int) -> Bool {
    if userIQ > 10 {
        return false
    }
}

同样,我想用闭包定义一个函数,如果闭包永远不会返回,也不会编译。例如,下面的代码可能永远不会返回completionHandler:

代码语言:javascript
复制
func isTheEarthFlat(withUserIQ userIQ: Int, completionHandler: (Bool) -> Void) {
    if userIQ > 10 {
        completionHandler(false)
    }
}

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

EN

回答 3

Stack Overflow用户

发布于 2017-08-29 17:17:27

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

这是一个有趣的想法,可能会对语言进行有益的增强。可能是参数声明中某个地方的required关键字。

票数 2
EN

Stack Overflow用户

发布于 2017-08-29 17:23:32

对于您想要的内容没有特殊的关键字。但是,您可以考虑一种有趣的方法,即不会编译:

代码语言:javascript
复制
func isTheEarthFlat(withUserIQ userIQ: Int, completionHandler: (Bool) -> Void) {
    let result: Bool
    defer {
       completionHandler(result)
    }
    if userIQ > 10 {
        result = false
    }
}

这样做就可以了,completionHandler被迫被调用:

代码语言:javascript
复制
func isTheEarthFlat(withUserIQ userIQ: Int, completionHandler: (Bool) -> Void) {
    let result: Bool
    defer {
       completionHandler(result)
    }
    if userIQ > 10 {
        result = false
    } else {
        result = true
    }
}

不确定这是个很好的模式。

票数 2
EN

Stack Overflow用户

发布于 2017-08-29 17:29:22

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

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

GuarenteedExecutionResult是执行GuarenteedExecution的结果。诀窍是有一个想要的函数,例如isTheEarthFlat,返回一个GuarenteedExecutionResult。获得GuarenteedExecutionResult实例的唯一方法是在GuarenteedExecution上调用execute(argument:)。实际上,负责保证返回的类型检查器特性现在被用来保证GuarenteedExecution的执行。

代码语言:javascript
复制
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):

代码语言:javascript
复制
let guarenteedExecutionClosure = GuarenteedExecution(ofClosure: {
    print("This must be called!")
})

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

_ = doSomething(guarenteedCallback: guarenteedExecutionClosure)
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45944695

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档