考虑以下代码:
import SwiftUI
class ViewModel: ObservableObject {
}
struct TestView: View {
@ObservedObject var vm = ViewModel()
var body: some View {
// self.sample
GeometryReader { _ in
self.sample
}
}
var sample: some View {
Text("Hello, World!")
}
}
struct Tabs : View {
@State var selection: Int = 0
var body: some View {
TabView(selection: $selection) {
TestView().tabItem {
Text("First Tab")
}
.tag(0)
Text(String(selection))
.tabItem {
Text("Second Tab")
}
.tag(1)
}
}
}
struct TestView_Previews: PreviewProvider {
static var previews: some View {
TestView()
}
}有两个页签,在body中引用了selection,所以当selection发生变化时,会调用body。TestView正在使用GeometryReader。当我从“第一个选项卡”切换到“第二个选项卡”时,ViewModel被再次创建,并且从未被取消引用。这是出乎意料的。如果我切换100次,就会有100个ViewModels从SwiftUI内部引用。
不过,如果我删除GeometryReader,它会按预期工作。
有没有人体验过?有什么变通方法吗?我只是希望将此ViewModel生命周期绑定到TestView生命周期。
更新:
XCode 11.3.1 iOS 13.3
发布于 2020-01-22 17:57:26
好的,让我们在ViewModel中进行以下更改
class ViewModel: ObservableObject {
init() {
print(">> inited") // you can put breakpoint here in Debug Preview
}
}现在我们可以看到,因为View是值类型
struct TestView: View {
@ObservedObject var vm = ViewModel() // << new instance on each creation
...它起源于
var body: some View {
TabView(selection: $selection) {
TestView().tabItem { // << created on each tab switch
...因此,解决方案是在TestView之外创建ViewModel,并通过.environmentObject或构造函数参数注入外部实例。
顺便说一句,它不依赖于GeometryReader。使用Xcode11.2.1/ iOS 13.2测试
https://stackoverflow.com/questions/59856647
复制相似问题