我有一个包含多个项目的列表,这些列表打开一个DetailView,后者又包含一个视图模型。该视图模型应该具有一个服务类,该服务类将在详细视图出现时初始化,并应在向后导航时取消初始化。
但是,第一个问题是,在下面的示例中,将同时创建所有3个ViewModel实例(显示ContentView时),并且从不从内存中释放(deinit
永远不会被调用。)
struct ContentView: View {
var body: some View {
NavigationView {
List {
NavigationLink(destination: DetailView()) {
Text("Link")
}
NavigationLink(destination: DetailView()) {
Text("Link")
}
NavigationLink(destination: DetailView()) {
Text("Link")
}
}
}
}
}
struct DetailView: View {
@ObservedObject var viewModel = ViewModel()
var body: some View {
Text("Hello \(viewModel.name)")
}
}
class ViewModel: ObservableObject {
@Published var name = "John"
private let heavyClient = someHeavyService()
init() { print("INIT VM") }
deinit { print("DEINIT VM") }
}
这可能只是SwiftUI的工作方式,但是我很难思考一种处理类对象的方法,这些类对象是详细视图状态的一部分,但不应实例化,直到详细视图真正出现为止。一个示例是带有会议室的视频会议应用程序,其中建立连接的会议室客户端等应该仅在实际进入会议室时初始化,而在离开会议室时取消初始化。
对于有关如何进行管理的任何建议,我将不胜感激。我应该在heavyClient
上初始化onAppear
还是类似的东西?
答案 0 :(得分:0)
问题在于DetailView()
正在作为导航链接的一部分进行初始化。一种可能的解决方案是this post中的LazyView
。
实现如下:
struct LazyView<Content: View>: View {
let build: () -> Content
init(_ build: @autoclosure @escaping () -> Content) {
self.build = build
}
var body: Content {
build()
}
}
然后将DetailView()包裹在LazyView()中:
struct ContentView: View {
var body: some View {
NavigationView {
List {
NavigationLink(destination: LazyView(DetailView())) {
Text("Link")
}
NavigationLink(destination: LazyView(DetailView())) {
Text("Link")
}
NavigationLink(destination: LazyView(DetailView())) {
Text("Link")
}
}
}
}
}
这种解决方法的唯一问题是,尽管有很大的改进,但似乎总是有一个ViewModel实例存在。