【发布时间】: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属性 -
好吧,到目前为止,我红了太多文档并遵循了太多教程,我只是错过了这个明显的解决方案。谢谢你,先生。请发布它,而不是我可以接受的解决方案。