【问题标题】:Why its impossible to cast `(()->Void)` to `(()->Void)?`为什么无法将 `(()->Void)` 转换为 `(()->Void)?
【发布时间】:2020-09-10 04:59:10
【问题描述】:

我有一个接受请求的函数和一个可选的服务器响应回调:

static func getData(request: NSMutableDictionary?, callback: ((Dictionary<String, Any>) -> Void)? ) {
    // ...
}

我想为此函数编写一个包装器,其中参数不是可选的。我是这样做的:

static func getData(id: CLong, callback: ((Dictionary<String, Any>) -> Void) ) {
    getData(request: ["userId" : id], callback: callback)
}

问题是swift无法将((Dictionary&lt;String, Any&gt;) -&gt; Void)类型转换为((Dictionary&lt;String, Any&gt;) -&gt; Void)?类型。我不知道为什么。毕竟,我们可以成功地将非可选转换为可选:

var a = "hello"
var b: String? = a // correct

为什么 swift 做不到呢?为什么 Swift 认为 Type ((Dictionary&lt;String, Any&gt;) -&gt; Void) 和 Type ((Dictionary&lt;String, Any&gt;) -&gt; Void)? 是完全不同的类型,而不是同一类型的可选变体?

【问题讨论】:

  • 规则是可选变量可能为零,非选项变量永远不会为零。在您的情况下,您正在尝试将可选值设置为非可选。因此,每当您的可选值为零时,都会出现异常。迅速避免该异常不让您施放。

标签: ios swift lambda


【解决方案1】:

当一个闭包被包裹在一个可选项中时,该闭包“逃逸”。如果您不知道“转义”是什么意思,请阅读this answer of mine

然而,第二个getData 中的非可选闭包不是@escaping。所以你正在尝试制作一个非转义闭包escape!此处的错误消息有点令人困惑,但如果您直接传递 .some(callback) 而不是 callback,就会清楚发生了什么:

将非转义参数 'callback' 转换为泛型参数 'Wrapped' 可能会允许它转义

所以你应该在第二个getData 中将callback 标记为@escaping

func getData(id: CLong, callback: @escaping ((Dictionary<String, Any>) -> Void) ) {

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多