【问题标题】:Access EnvironmentObject from ViewModel in SwiftUI在 SwiftUI 中从 ViewModel 访问 EnvironmentObject
【发布时间】:2020-03-02 19:00:11
【问题描述】:

我需要在 SwiftUI 中实现一个不太复杂的用例: 使用用户名和密码登录,authToken 和 refreshToken 从 API 中返回,将 refreshToken 存储在 KeyChain 中,将 authToken 存储在 AppState 中(这是一个 ObservableObject(环境对象),代码如下)。如果我的任何请求返回 401 HTTP 响应代码(因此 accessToken 已过期),我需要刷新 accessToken 并使用新令牌重试我的原始请求。但问题是我从 ViewModel 调用 RefreshTokenRequest,我无法通过 View 将令牌“返回”到 appState。所以问题是,我怎样才能从我的 ViewModel 访问我的 environmentObject?可能吗?这是我在操场文件中简化的代码:

class AppState: ObservableObject {
    @Published var isLoggedIn: Bool = false
    @Published var token: String = ""
}

struct ProtectedView: View {
    @EnvironmentObject var appState: AppState

    var body: some View {
        VStack {
            RollerListView(token: self.appState.token)
        }
    }
}

struct Roller: Codable, Hashable {
    var scooter_name: String;
}

class RollerListVM: ObservableObject {
    @Published var rollers = [Roller]()

    func getRollers(token: String) {
        print("FETCHING ROLLERS...")
        /// Here's my API request to get the array of rollers. If the token is expired, I need to refresh it with a new request and I need to pass the new token to the appState.token variable, because I need to use the new token in all of my request instead of expired one.
        /// IF THE TOKEN IS REFRESHED, HOW CAN I PASS IT TO THE AppState.token ???
        DispatchQueue.main.async {
            self.rollers = [Roller(scooter_name: "scooter 1"), Roller(scooter_name: "scooter 2")]
        }
    }

    init(token: String) {
        self.getRollers(token: token)
    }
}

struct RollerListView: View {
    @ObservedObject private var rollerListVM: RollerListVM;
    @EnvironmentObject var appState: AppState

    var body: some View {
        List(rollerListVM.rollers, id: \.self) { roller in
            HStack {
                Text(roller.scooter_name)
            }
        }
    }

    init(token: String) {
        self.rollerListVM = RollerListVM(token: token)
    }
}

我尝试将闭包函数传递给 ViewModel 并在令牌刷新后调用它(以新令牌作为参数),但它不起作用,因为 self 参数在闭包内发生了变异。

我该怎么做?

【问题讨论】:

  • 不要使用令牌字符串初始化RollerListVM 等,而是传递AppState 对象并让视图模型根据需要从中获取令牌。如果令牌已过期,请在 AppState 对象上调用 refreshToken 方法,以便更新其 token 属性
  • 好吧,到目前为止,我红了太多文档并遵循了太多教程,我只是错过了这个明显的解决方案。谢谢你,先生。请发布它,而不是我可以接受的解决方案。

标签: ios swift xcode swiftui


【解决方案1】:

由于您的token 有点动态,我建议您不要将它直接传递给您的视图模型。相反,传递AppState 对象并在需要时检索token

如果您检测到过期令牌,您可以调用AppState 上的函数,该函数获取刷新令牌并更新其token 属性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-30
    • 2020-05-24
    • 2020-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-05
    • 1970-01-01
    相关资源
    最近更新 更多