如何使用这样的闭包参数初始化结构?

Posted

技术标签:

【中文标题】如何使用这样的闭包参数初始化结构?【英文标题】:How can you initialize a struct with a closure parameter like this? 【发布时间】:2021-12-30 14:21:09 【问题描述】:

在this question我今天看到它定义了一个结构Effect,它有一个属性run,它是一个带有通用参数的闭包:

struct Effect<T> 
    let run: (@escaping (T) -> Void) -> Void

然后示例代码创建一个Effect&lt;Int&gt; 的实例,并使用类似于尾随闭包语法的东西指定run 属性的闭包:

let anIntInTwoSeconds = Effect<Int>  callback in
    DispatchQueue.main.asyncAfter(deadline: .now() + 2) 
        callback(42)
    

是什么使它合法?我希望需要在调用 init 方法时明确指定 run 参数:

let anIntInTwoSeconds = Effect<Int>(run:  callback in
    DispatchQueue.main.asyncAfter(deadline: .now() + 2) 
        callback(42)
    

)

任何一个版本都可以编译和工作。 Swift 中的什么使第一个版本合法?我不知道如何构建问题以便寻找答案。

【问题讨论】:

【参考方案1】:

这就像任何最后一个参数是函数的函数一样。尾随闭包语法是尾随闭包语法。该函数是一个初始化器这一事实没有任何改变。

所以让我分阶段进行。你知道你可以说:

func myfunc(whatever: () -> ()) 
myfunc 

好的,但现在让我们让它成为一个静态方法:

struct S 
    static func myfunc(whatever: () -> ()) 

S.myfunc 

好的,但是init 一个静态方法——它只是一个静态方法,你可以省略它的名字:

struct S 
    let whatever: () -> ()

S  // meaning S.init 

【讨论】:

嗯。我从来没有想过你可以在调用初始化程序时使用尾随闭包语法,但我想这是有道理的。 很多很多内置库类型都使用它,我很惊讶你直到现在才注意到。当然 SwiftUI 完全依赖于这种东西。 好吧,我从来没有完全理解 SwiftUI 用于创建 View 对象的语法,但现在它非常有意义。我太迟钝了。 ??????☀️?

以上是关于如何使用这样的闭包参数初始化结构?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Rust 的结构中存储闭包?

如何在swift中初始化闭包变量?

如何存储和使用接受引用并返回未来的可选闭包?

Laravel 中的闭包参数是如何传入的

无法使用闭包使用 alamofire 解析 json

如何修复上下文闭包类型 '((String, JSON), (String, JSON)) -> Bool' 需要 2 个参数,但在闭包体中使用了 1 个?