Swift 4 Codable 和泛型

Swift 4 Codable & generics

提问人:Morniak 提问时间:10/12/2017 最后编辑:Paulo MattosMorniak 更新时间:11/28/2017 访问量:4412

问:

我正在使用 PINCache 向我的应用程序添加缓存,并且我处于缓存系统调用用于编码/解码的委托方法的情况。 这些方法是泛型的,但泛型值不明确符合 。因为他们是委托人,所以我无法更改签名以使泛型类型符合 .CodableCodable

func modelForKey<T : SimpleModel>(_ cacheKey: String?, context: Any?, completion: @escaping (T?, NSError?) -> ()) {
    guard let cacheKey = cacheKey, let data = cache.object(forKey: cacheKey) as? Data, T.self is Codable else {
        completion(nil, nil)
        return
    }

    let decoder = JSONDecoder()
    do {
        let model: T = try decoder.decode(T.self, from: data)
        completion(model, nil)
    } catch {
        completion(nil, nil)
    }
}

使用此代码,我遇到以下错误:

在参数类型中,不符合预期类型T.TypeTDecodable

如何强制接受通用值?decoder

Swift 泛型 Swift4 Codable

评论

0赞 Paulo Mattos 10/13/2017
您能否也添加调用该函数的代码?谢谢;)modelForKey<T>

答:

0赞 Paolo 10/12/2017 #1

更改此行以检查它是否符合:Decodable

guard let cacheKey = ... as? Data, T.self is Decodable else {

评论

0赞 Morniak 10/12/2017
和我的代码有什么区别?我已经在检查如果是.T.selfDecodable
0赞 Paolo 10/12/2017
@Morniak你在哪里检查?
0赞 Morniak 10/12/2017
我的守卫的最后指示(第 2 行)
0赞 Paolo 10/12/2017
@Morniak 在包含的代码中,您正在检查 notCodableDecodable
1赞 Morniak 10/12/2017
哦对了 !但 Codable 暗示了 Decodale。无论如何,我尝试使用Decodable,但遇到了同样的问题。检查类型时,不会更改作用域中变量的类型。Codable 系统需要真实类型,所以我不能将我的 var 转换为 Codable。
4赞 ahbou 10/13/2017 #2

由于 Codable 还不能在扩展中实现,并且 SimpleModel 是 PINCache 的内部版本,因此无法使其符合 Codable。

如果可能的话,我建议切换到具有支持 Codable 的协议的缓存库,例如 Cache

4赞 Oliver Langan 10/25/2017 #3

尝试要求将该类型限制为 Decodable。func modelForKey<T : SimpleModel, Decodable> ...

0赞 longcatislooong 11/23/2017 #4

IMO 问题不在于 PINCache。

T.self is Codable不会告诉编译器有关类型的更多信息,因此不会通过类型检查,即使是 .Tdecoder.decode(T.self, from: data)TDecodable

我认为分叉 RocketData 将是这里最简单的解决方案(如果您想继续使用 RocketData + 并且您的所有模型都符合)。使符合 。DecodableDecodableSimpleModelDecodable

0赞 Paul T. 11/28/2017 #5
  1. 尝试创建CustomProtocol: Codable, SimpleModel

  2. 如果第 1 点不起作用,请尝试创建自定义类并使用CustomClass: SimpleModel, CodablemodelForKey<T : CustomClass>