我正在用SwiftUI构建一个电子商务应用程序,需要在加载许多视图之前从服务器检索一些数据。我想知道正确的方法来检索和存储这些数据。
目前,在主页上,应用程序向服务器请求一些要显示的图片的名称,然后使用AsyncImage
从服务器加载每个图片。目前,我正在视图中创建一个@State
变量来存储图像名称,并在.task
中加载数据:
struct CoverImagesTabView: View {
@State var coverImageNames: [String] = []
var body: some View {
TabView {
ForEach(coverImageNames, id: .self) { coverImage in
CoverImageView(coverImage: coverImage)
.padding(.top, 10)
.padding(.horizontal, 15)
} //: LOOP
} //: TAB
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .always))
.task {
await getCoverImageNames { imageNames in
coverImageNames = imageNames
}
}
}
}
与getCoverImageNames
函数看起来像
import Alamofire
func getCoverImageNames(_ callback: @escaping (_ decoded: [String]) -> Void) async {
AF.request("http://(serverIP)/api/offerings/marketing/coverImages")
.responseDecodable(of: [String].self) { response in
if response.value != nil {
callback(response.value ?? [])
print("Cover image names retrieved")
} else {
print("Could not access cover image names")
}
}
}
然后在CoverImageView
中使用coverImageNames
来加载图像。我计划使用相同的策略来检索其他数据,例如产品列表。
这个方法有点笨拙,主要是因为它每次重新加载视图时都会调用API来设置coverImageNames
的值;这些数据实际上只需要在每次应用启动时加载一次。在Swift中有特定的方法来做到这一点吗?
如果我创建一个符合ObservableObject
的类,并将它的一个实例作为@StateObject
传递给这个视图,它解决了重新加载问题,但如果我必须创建一个全新的类,只是为了表示[String]
,它只加载一次,这不是很有效。
我还考虑过使用Core Data来保存服务器上的数据,但这似乎有点过头了。
是否有一个内置的方式来加载我的数据一次,然后继续重用它每次视图被重新加载?还是状态对象方法是最有效/唯一的方法?
我会创建一个Observable类,并通过@EnvironmentObject在整个应用程序中共享它的一个实例。
如果加载一次后没有改变,就不需要使用@StateObject,因为不需要更新视图。
class YourModel : ObservableObject {
var coverImageNames: [String] = []
init() {
fetchImageNames()
}
func fetchImageNames() {
// load the names of `some` images from the server using URLSession or whatnot and update coverImageNames
}
}
struct YourApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(YourModel())
}
}
}
struct YourView1: View {
@EnvironmentObject var m: YourModel
var body: some View {
// use m.coverImageNames
}
}
struct YourView2: View {
@EnvironmentObject var m: YourModel
var body: some View {
// use m.coverImageNames
}
}
如果你不喜欢在每个视图中重复调用AsyncImage,我会在init期间构建一个UIImage集合,以便它可以在任何视图中重用。构建集合可以是同步的或异步的,两者都有利弊,这取决于情况,所以这是你的选择。