Capturing closures within closures: Xcode throws error: Escaping closure captures non-escaping parameter

Capturing closures within closures: Xcode throws error: Escaping closure captures non-escaping parameter

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

案例 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 声明,但这是不允许的。

以下在 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()
        }
    })