我从编译器中得到一些奇怪的行为我无法弄清楚(Xcode 8,Swift 3),因为我正在尝试从Swift 2迁移我的代码。我认为它与元组有关,但是我我不完全确定。
我有一个定义了几个泛型的泛型类。在那些泛型中,我还有一些类型别名的设置和使用它们的函数:
open class GuardPool <Key: Hashable, Resource> {
public typealias ResourceCallback = ([Resource]) -> Void
public typealias Request = (keys: Set<Key>, cb: ResourceCallback)
fileprivate var pendingRequests: [Request] = []
open func request(_ keys: Set<Key>, cb: ([Resource]) -> Void) {
let pendingRequest: Request = (keys: keys, cb: cb)
pendingRequests.append(pendingRequest)
}
}
在作业(let pendingRequest: Request = ...
)上,我收到此错误:
Cannot convert value of type 'Set<Key>' to specified type 'Set<_>'
我无法弄清楚如何解决这个问题。似乎编译器无法识别Set
的类型信息。
注意:显然,这个类要大得多。我复制并粘贴了相关代码,而不是插入300行。
答案 0 :(得分:0)
错误消息具有误导性。如果你删除 第二行中的(不必要的)显式类型注释
let pendingRequest = (keys: keys, cb: cb)
然后编译器声明
error: non-escaping parameter 'cb' may only be called note: parameter 'cb' is implicitly non-escaping
显示实际问题:cb
参数必须标记为@escaping
因为
它存储在一个属性中,可能会在以后调用,
从request
方法返回后:
open func request(_ keys: Set<Key>, cb: @escaping ([Resource]) -> Void) {
let pendingRequest = (keys: keys, cb: cb)
pendingRequests.append(pendingRequest)
}
在Swift 2中,默认情况下,闭包是逃避的,可以标记
与@noescape
。在Swift 3中,默认情况下,闭包是非转义的,
比较SE-0103: Make non-escaping closures the default。