SwiftUI如何在viewModel init中使用envimentobject ?



我有一个基本的API:

class API: ObservableObject {
@Published private(set) var isAccessTokenValid = false
@AppStorage("AccessToken") var accessToken: String = ""
@AppStorage("RefreshToken") var refreshToken: String = ""
func request1() {}
func request2() {}
}

通过.environmentObject(API())传递给所有视图。所以在任何视图中都可以很容易地访问API来做http请求调用。

我也有一个视图模型来获取一些数据的视图出现:

class ViewModel: ObservableObject {
@Published var data: [SomeResponseType]
init() {
// do the request and then init data using the response
}
}
struct ViewA: View {
@StateObject private var model = ViewModel()
var body: View {
VStack {
model.data...
}
}
}

但在init()中,ViewModel中的API不可访问。

所以,为了解决这个问题,我找到了三个解决方案:

解决方案1:将API更改为Singleton:

class API: ObservableObject {
static let shared = API()
...
}

我们还应该将enviromentObject(API())改为enviromentObject(API.shared)

在ViewModel中,它可以使用API。直接共享。

方案2:调用onAppear/task上的请求

struct ViewA: View {
@EnvironmentObject var api: API
@State private var data: [SomeResponseType] = []
var body: View {
VStack {}
.task {
let r = try? await api.request1()
if let d = r {
data = d
}
}
}
}

解决方案3:设置viewmodelonappear/task的API

class ViewModel: ObservableObject {
@Published var data: [SomeResponseType]
var api: API?
setup(api: API) { self.api = api }
requestCall() { self.api?.reqeust1() }
}
struct ViewA: View {
@EnvironmentObject var api: API
@StateObject private var model = ViewModel()
var body: View {
VStack {}
.onAppear {
model.setup(api)
model.requestCall()
}
}
}

尽管如此,我仍然认为他们不是一个SwiftUI方式。我的问题是一个XY问题。可能,根本问题是如何重构我的API。但是我是SwiftUI的新手。

解决方案2是最好的。您还可以尝试/捕获异常并为错误消息设置@State

尽量避免使用UIKit样式的视图模型对象,因为在SwiftUI中View数据结构加上@State已经完成了这个角色。只有当你需要视图数据的引用类型时,你才需要@StateObject,现在我们有.task

相关内容

  • 没有找到相关文章