使用 Moya 处理缓存
Posted
技术标签:
【中文标题】使用 Moya 处理缓存【英文标题】:Cache Handling with Moya 【发布时间】:2018-01-30 08:16:40 【问题描述】:我们在项目中将 Moya、RxSwift 和 Alamofire 实现为 pod。
有谁知道您如何使用这项技术控制每个 url 请求的缓存策略?
我在 Moya 的 GitHub 页面上阅读了很多问题,但仍然找不到任何东西。还尝试使用存储为 sampleData 文件的实际 json 响应,如下所示:
var sampleData: Data
guard let path = Bundle.main.path(forResource: "SampleAggregate", ofType: "txt") else
return "sampleData".utf8Encoded
let sample = try? String(contentsOfFile: path, encoding: String.Encoding.utf8)
return sample!.utf8Encoded
提前感谢任何专业提示:)
【问题讨论】:
【参考方案1】:据我了解,解决此问题的“最干净”的方法是使用自定义 Moya 插件。这是一个实现:
protocol CachePolicyGettable
var cachePolicy: URLRequest.CachePolicy get
final class CachePolicyPlugin: PluginType
public func prepare(_ request: URLRequest, target: TargetType) -> URLRequest
if let cachePolicyGettable = target as? CachePolicyGettable
var mutableRequest = request
mutableRequest.cachePolicy = cachePolicyGettable.cachePolicy
return mutableRequest
return request
要真正使用这个插件,还需要两个步骤:
插件应该像这样添加到您的 Moya 提供程序中:
let moyaProvider = MoyaProvider<YourMoyaTarget>(plugins: [CachePolicyPlugin()])
YourMoyaTarget
应该符合CachePolicyGettable
,从而为每个目标定义缓存策略:
extension YourMoyaTarget: CachePolicyGettable
var cachePolicy: URLRequest.CachePolicy
switch self
case .sampleTarget, .someOtherSampleTarget:
return .reloadIgnoringLocalCacheData
default:
return .useProtocolCachePolicy
注意:此方法使用协议将缓存策略与目标类型相关联;也可以通过传递给插件的闭包来实现这一点。然后,此类闭包将根据作为输入参数传递给闭包的目标类型来决定使用哪个缓存策略。
【讨论】:
非常好的答案。我只是想知道回复会保存多长时间。 实际的缓存是通过底层的 URLRequest 处理的——所以要了解它在做什么,你必须在那里做一些研究【参考方案2】:根据@fredpi 的回答,我稍微改进了 Moya 的缓存插件。以下是我的版本:
import Foundation
import Moya
protocol CachePolicyGettable
var cachePolicy: URLRequest.CachePolicy get
final class NetworkDataCachingPlugin: PluginType
init (configuration: URLSessionConfiguration, inMemoryCapacity: Int, diskCapacity: Int, diskPath: String?)
configuration.urlCache = URLCache(memoryCapacity: inMemoryCapacity, diskCapacity: diskCapacity, diskPath: diskPath)
func prepare(_ request: URLRequest, target: TargetType) -> URLRequest
if let cacheableTarget = target as? CachePolicyGettable
var mutableRequest = request
mutableRequest.cachePolicy = cacheableTarget.cachePolicy
return mutableRequest
return request
extension NetworkApiService: CachePolicyGettable
var cachePolicy: URLRequest.CachePolicy
switch self
case .getUserProfile:
return .returnCacheDataElseLoad
default:
return .useProtocolCachePolicy
为了清除缓存,您需要访问 urlRequest 对象/对象。如何检索 Moya 路由的 urlRequest,您可以在 following 主题中找到。
要清除缓存,您可以使用以下代码:
public func clearCache(urlRequests: [URLRequest] = [])
let provider = ... // your Moya provider
guard let urlCache = provider.manager.session.configuration.urlCache else return
if urlRequests.isEmpty
urlCache.removeAllCachedResponses()
else
urlRequests.forEach urlCache.removeCachedResponse(for: $0)
【讨论】:
【参考方案3】:子类MoyaProvider
并组合requestClosure
。
它应该看起来像:
final class MyProvider<Target: TargetType>: MoyaProvider<Target>
public init(
endpointClosure: @escaping EndpointClosure = MoyaProvider.defaultEndpointMapping,
requestClosure: @escaping RequestClosure = MoyaProvider.defaultRequestMapping,
stubClosure: @escaping StubClosure = MoyaProvider.neverStub,
manager: Manager = MoyaProvider<Target>.defaultAlamofireManager(),
plugins: [PluginType] = [],
trackInflights: Bool = false
)
super.init(
endpointClosure: endpointClosure,
requestClosure: endpoint, closure in
var request = try! endpoint.urlRequest() //Feel free to embed proper error handling
if request.url == URL(string: "http://google.com")!
request.cachePolicy = .returnCacheDataDontLoad
else
request.cachePolicy = .reloadIgnoringLocalAndRemoteCacheData
closure(.success(request))
,
stubClosure: stubClosure,
manager: manager,
plugins: plugins,
trackInflights: trackInflights
)
【讨论】:
【参考方案4】:如果您也想禁用存储的 cookie
request.httpShouldHandleCookies = false
【讨论】:
以上是关于使用 Moya 处理缓存的主要内容,如果未能解决你的问题,请参考以下文章