封装了几个网络请求:
class API: ObservableObject { @Published private(set) var isAccessTokenValid = false @AppStorage("Passcode") var passcode: String = "" @AppStorage("AccessToken") var accessToken: String = "" @AppStorage("RefreshToken") var refreshToken: String = "" privite func request() async throws -> (T?, URLResponse?) where T : Decodable { // 省略具体实现 } func request1() async throws -> SomeResponseType {} func request2() async throws -> SomeResponseType {} func request3() async throws -> SomeResponseType {} } 在 @main 中, 使用 .environmentObject(API()) 将网络请求加入到全局环境中, 在每个页面用到它的地方使用 @EnvironmentObject var api: API 来获取.
比如进入页面 A 需要进行网络请求, 则:
struct A: 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 } } } } 但这样的代码是 UIKit 的思路, 在 SwiftUI 中应该使用 Model 层进行网络请求, 应该这样添加一层 Model:
class ModelA: ObservableObject { @Published var data: [SomeResponseType] init() { // do the request and then init data using the response } } 在页面中只需要
struct A: View { @StateObject private var model = ModelA() var body: View { VStack { model.data... } } } 但现在问题出现了, 在 Model 里面无法直接使用上面封装的 API, 也就是在 model 的初始化函数中, 无法获取 environment 数据. 于是只能修改一下 API, 使其变成单例:
class API: ObservableObject { static let shared = API() ... } 这样在 model 里直接可以使用它了.
虽然这样看起来解决了, 但感觉代码结构还需要调整一下, 但不知道如何调整. 请大佬指点指点
