首页 > 解决方案 > 在闭包内捕获闭包:Xcode 抛出错误:转义闭包捕获非转义参数

问题描述

我试图在另一个闭包中捕获一个闭包(使用它返回响应),但是当我这样做时(案例 2),我得到一个错误。我的意图是second在 URLSession 的响应中使用,但不幸的是我不能。

案例1:有效(只是打印,因为没有内部封闭)

import UIKit
class Callback {
//    let callback: (String, (String?) -> Void) -> Void
    let callback: (String, String) -> Void
    public init(callback: @escaping ((String, String) -> Void)) {
        self.callback = callback
    }
}

Callback { first, second in
    let url = URL(string: "https://testapi.com")!
    URLSession.init().dataTask(with: url) { data, response, error in
        print(second)
    }
}

案例 2:错误。Escaping closure captures non-escaping parameter 'second'

import UIKit
class NestedCallback {
//    let callback: (String, (String?) -> Void) -> Void
    let callback: (String, () -> Void) -> Void
    public init(callback: @escaping ((String, () -> Void) -> Void)) {
        self.callback = callback
    }
}

NestedCallback { first, second in
    let url = URL(string: "https://testapi.com")!
    URLSession.init().dataTask(with: url) { data, response, error in <---- error: Escaping closure captures non-escaping parameter 'second'
        second()
    }
}

我已经简化了代码,但实际上我将使用second这种方式来发送带有参数的数据。(第二个将有2个参数,数据和错误)

我确实考虑为嵌套回调添加另一个 @escaping声明,但这是不允许的。

标签: swiftxcodeclosures

解决方案


以下在 Swift 5.4 中编译良好:

import UIKit
class NestedCallback {
    let callback: (String, @escaping () -> Void) -> Void
    public init(callback: @escaping ((String, @escaping () -> Void) -> Void)) {
        self.callback = callback
    }
}


    NestedCallback(callback: { first, second in
        let url = URL(string: "https://testapi.com")!
        URLSession.init().dataTask(with: url) { data, response, error in
            second()
        }
    })

推荐阅读