We have implemented Moya, RxSwift And Alamofire as pods in our project.
Does anyone know how you gain control of the cache policies per url request using this tech?
I have read through quite a few of the issues on Moya's GitHub page but still can't find anything. Also tried using actual json response stored as files for the sampleData like so:
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
}
Thanks in advance for any pro tips :)
As to my understanding, the "cleanest" way to solve this, is to use a custom Moya Plugin. Here's an implementation:
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
}
}
To actually use this plugin, there are two required steps left:
The plugin should be added to your Moya provider like this:
let moyaProvider = MoyaProvider<YourMoyaTarget>(plugins: [CachePolicyPlugin()])
YourMoyaTarget
should conform to CachePolicyGettable
and thereby define the cache policy for each target:
extension YourMoyaTarget: CachePolicyGettable {
var cachePolicy: URLRequest.CachePolicy {
switch self {
case .sampleTarget, .someOtherSampleTarget:
return .reloadIgnoringLocalCacheData
default:
return .useProtocolCachePolicy
}
}
}
Note: This approach uses a protocol to associate cache policies with target types; one could also realise this via a closure being passed to the plugin. Such closure would then decide which cache policy to use depending on the target type passed as an input parameter to the closure.
Based on @fredpi answer, I slightly improved caching plugin for Moya. Below is my version:
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
}
}
}
In order to clear the cache, you need to have an access to urlRequest object/objects. How to retrieve an urlRequest for Moya route you can find in the following topic.
To clear the cache you can use following code:
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) }
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With