【问题标题】:How can I cache this response from my API to prevent additional calls?如何从我的 API 缓存此响应以防止额外调用?
【发布时间】:2019-07-30 04:57:00
【问题描述】:

以下面的服务为例

import Foundation
import PromiseKit

protocol ProfileServiceType {
    func fetchCurrentUser() -> Promise<Profile>
}

struct ProfileService: ProfileServiceType {

    private let httpClient: HTTPClientProtocol

    init(httpClient: HTTPClientProtocol) {
        self.httpClient = httpClient
    }

    func fetchCurrentUser() -> Promise<Profile> {
        return httpClient.call(endpoint: ProfilesEndpoint.byUserId, method: .get, urlParams: nil, queryParams: nil, bodyParams: nil)
    }
}

当我获取当前用户时,我会返回他们的个人资料,例如,我的应用中有多个场景可能需要用户个人资料的某些方面,例如他们的userId。每次我使用此方法时,它都会发出网络请求。由于此调用是在我的应用首次启动时进行的,因此我可以肯定地说,在任何其他场景或服务需要它之前,我已经获取了这些数据。

我在想这样的事情,但是我需要实现一个我相信的单例模式

   var cachedProfile: Profile?

    func fetchCurrentUser() -> Promise<Profile> {
        return Promise<Profile> { [weak self] seal in
            return httpClient.call(endpoint: ProfilesEndpoint.byUserId, method: .get, urlParams: nil, queryParams: nil, bodyParams: nil)
                .done { (value: Profile) in
                    self?.cachedProfile = value
                    seal.fulfill(value)
                }.catch { err in
                    seal.reject(err)
            }
        }
    }

最近来自 F/E 开发并大量使用 redux,这对我来说是新事物,在处理 iOS 开发时我不是很清楚。

【问题讨论】:

    标签: ios swift caching


    【解决方案1】:

    在您的fetchCurrentUser 中,您可以检查您的cachedProfile 是否不是nil,然后您就可以从那里返回。

    如果是nil,则可以继续进行网络调用。我不认为你真的必须在这里使用单例。

    【讨论】:

    • 那么,如果另一个场景或控制器联系到ProfileService,它不会是一个新实例吗?所以这个值是零?
    • 这实际上取决于您的ProfileService 实现。如果所有其他视图都有自己的实例,那么是的,它将创建新实例。但我认为您也可以将相同的对象传递给所有不同的视图。或者您可以将 cachedProfile 保留为 singleton。 :)
    【解决方案2】:

    您可以将传入的值保存到 UserDefaults 中,如果存在则返回,否则转到网络请求并保存对象。

    func fetchCurrentUser() -> Promise<Profile> {
        return Promise<Profile> { [weak self] seal in
            if let data = UserDefaults.standard.object(forKey: "SavedProfile"),
                let savedProfile = try! NSKeyedUnarchiver.unarchivedObject(ofClass: Profile.self, from: data) as? Profile {
                seal.fulfill(savedProfile)
            } else {
                return httpClient.call(endpoint: ProfilesEndpoint.byUserId, method: .get, urlParams: nil, queryParams: nil, bodyParams: nil)
                    .done { (value: Profile) in
                        let data = try! NSKeyedArchiver.archivedData(withRootObject: value, requiringSecureCoding: true)
                        UserDefaults.standard.set(value, forKey: "SavedProfile")
                        seal.fulfill(value)
                    }.catch { err in
                        seal.reject(err)
                }
            }
        }
    }
    

    确保 Profile 对象符合编码协议。

    【讨论】:

      猜你喜欢
      • 2012-04-13
      • 2015-07-31
      • 2014-11-23
      • 1970-01-01
      • 2015-12-31
      • 1970-01-01
      • 2018-02-03
      • 2011-02-11
      • 2023-04-02
      相关资源
      最近更新 更多