提问者:小点点

Swift泛型-无法将值转换为类型


我对Swift中的泛型有意见。

我正在构建简单的http客户端,我想扩展它以添加缓存。 我已经建立了缓存解决方案使用这个优秀的帖子在这里。

我希望能够在缓存实例初始化时将其传递给我的客户机,因此它需要能够保存符合codable的不同数据类型。

到目前为止,我得到了以下内容(缓存实现如文章中所述):

数据:

struct CountryResult: Codable {
    let meta: Meta //confroms to Codable
    let results: [Country] //conforms to Codable
}

缓存:

final class Cache<Key: Hashable, Value> {
// cache implementation
}

// MARK: - Codable

extension Cache.Entry: Codable where Key: Codable, Value: Codable {}
extension Cache: Codable where Key: Codable, Value: Codable {
    convenience init(from decoder: Decoder) throws {
        self.init()

        let container = try decoder.singleValueContainer()
        let entries = try container.decode([Entry].self)
        entries.forEach(insert)
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        try container.encode(keyTracker.keys.compactMap(entry))
    }
}

http客户端:

struct HttpService {

    let service: BaseUrl
    let cache: Cache<URL, Codable>

    init(service: String = "https://some.service/api", cache: Cache<URL, Codable> = Cache()) {
        self.service = service
        self.cache = cache
    }

    // performs http get
    func get<T: Codable>(endpoint: String, completion: @escaping (T?, Error?) -> Void) {
        guard let url = buildUrl(endpoint) else {
            print("Invalid url")
            return
        }

        if let cachedData = cache[url] as? T {
            print("Cache hit for: \(url)")
            completion(cachedData, nil)
            return
        } else {
            print("Cache miss for: \(url)")
        }

        //data not in cache, go to network
        //....
    }

现在,我希望能够在将请求不同数据类型的不同视图控制器中实例化这个http客户端。 我还想单独持久化每个VC缓存,所以当初始化VC时,我试图找到缓存是否存储到磁盘,并像这样加载它:

let urls = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)
let cacheUrl = urls[0].appendingPathComponent("/v1/test.cache")
if let data = try? Data(contentsOf: cacheUrl) {
    let cache  = try? JSONDecoder().decode(Cache<URL, CountryResult>.self, from: data) ?? Cache<URL, CountryResult>()
    let httpClient = HttpService(service: "https://some.service/api", cache: cache) //ERROR
}

但我遇到以下错误,我并不完全理解:无法转换类型为“cache>?”的值。 应为参数类型“cache.” (又名“cache<;url,Decodable&encodable>;”)

如果countryresult符合codable也就是decodable&; 可编码


共1个答案

匿名用户

如果更改以下代码

let cache: Cache<URL, Codable>

作为

let cache: Cache<URL,T: Codable>

在HttpService结构中,希望它能工作。

根据Swift文件,在泛型中,允许具有符合类或协议或协议组合但不仅仅是协议的类型参数。