封装了几个网络请求:
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 里直接可以使用它了.
虽然这样看起来解决了, 但感觉代码结构还需要调整一下, 但不知道如何调整. 请大佬指点指点
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.