当前位置: 首页 > 知识库问答 >
问题:

用Moya处理缓存

云捷
2023-03-14

我们在我们的项目中实现了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

}

null

共有3个答案

姚高爽
2023-03-14

基于@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 object/objects的访问权限。如何检索Moya路由的urlRequest,可以在下面的主题中找到。

要清除缓存,可以使用以下代码:

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) }
    }
}
沈良策
2023-03-14

据我所知,解决这个问题的“最干净”的方法是使用自定义的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
    }
}

要实际使用这个插件,还需要两个步骤:

>

let moyaProvider = MoyaProvider<YourMoyaTarget>(plugins: [CachePolicyPlugin()])

null

extension YourMoyaTarget: CachePolicyGettable {
    var cachePolicy: URLRequest.CachePolicy {
        switch self {
        case .sampleTarget, .someOtherSampleTarget:
            return .reloadIgnoringLocalCacheData

        default:
            return .useProtocolCachePolicy
        }
    }
}

注意:这种方法使用协议将缓存策略与目标类型相关联;人们也可以通过传递给插件的闭包来实现这一点。然后,这样的闭包将根据作为输入参数传递给闭包的目标类型来决定使用哪个缓存策略。

许彦
2023-03-14

子类 和compose

它应该看起来像:

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
        )
    }

}
 类似资料:
  • Moya 是你的 app 中缺失的网络层。不用再去想在哪儿(或者如何)安放网络请求,Moya 替你管理。 Moya有几个比较好的特性: 编译时检查正确的API端点访问. 使你定义不同端点枚举值对应相应的用途更加明晰. 提高测试地位从而使单元测试更加容易.

  • 所以我试图弄清楚如何使用Realm,Moya和ObjectMapper。 我使用Moya向我的API发出请求。我使用Realm将返回的数据保存在本地数据库中。并且我使用ObjectMapper将JSON对象映射到校正领域变量。 然而,现在我遇到了一个问题,我不确定如何解码JSON响应以便将其通过映射器。 下面是我的莫亚密码: 错误发生在这一行: 类如下所示: 我明白为什么我会犯这个错误,但我不知道

  • 我目前正在从事一个项目,该项目同时包含spring data redis和spring Cache。在spring data redis中,我使用redis模板调用redis。我在try-catch块中处理redis模板引发的所有异常,如下所示: 我可以使用一个类似的try块来处理来自的异常吗?如何处理可缓存中的redis引发的异常?

  • You can supply a custom function to handle cache files instead of using the built-in method using the $cache_dir. See the custom cache handler function section for details. 你可以提供一个自定义函数来处理缓存文件,而不是通过变量

  • 几乎我的所有批处理都有一个读取器(JpaPagingItemReader从我的数据库读取数据)、一个处理器和一个创建XML文件的写入器。这3个部分都在一个步骤,我的块大小通常在50左右。 当发生可跳过的异常时,我注意到了两个副作用,我想知道是否有一种方法可以改变这些默认行为=> 我通常在阅读器中读取JPA实体,并将它们发送到处理器,在那里我将更改它们的属性以更新数据库。但是,当发生可跳过的异常并且

  • 我了解到,使用服务工作者进行脱机缓存与浏览器缓存类似。如果是这样的话,那么为什么您希望使用服务工作者进行此缓存?浏览器缓存将检查文件是否被修改,然后从缓存中提供服务,通过服务工作者,我们将从代码中处理相同的事情。默认情况下,浏览器具有该功能,那么为什么更喜欢服务人员呢?