当我尝试从 Swift 2 迁移我的代码时,我无法弄清楚编译器的一些奇怪行为(Xcode 8、Swift 3)。我认为这与元组有关,但我我并不完全确定。
我有一个泛型类,它定义了几个泛型。在这些泛型中,我还有几个类型别名的设置和一个使用它们的函数:
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)
}
}
在分配时 (letendingRequest: Request = ...
),我收到此错误:
Cannot convert value of type 'Set<Key>' to specified type 'Set<_>'
我不知道如何解决这个问题。编译器似乎无法识别 Set
的类型信息。
注意:显然,这个类比这个大得多。我复制并粘贴了相关代码,而不是插入 300 行。
最佳答案
该错误消息具有误导性。如果您删除 第二行中的(不必要的)显式类型注释
let pendingRequest = (keys: keys, cb: cb)
然后编译器指出
error: non-escaping parameter 'cb' may only be called note: parameter 'cb' is implicitly non-escaping
which reveals the actual problem: The cb
parameter must be marked as @escaping
because
it is stored in a property and might be called at a later time,
after returning from the request
method:
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 .
关于 swift 3 : Nested Generic Type,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39711381/