考虑以下代码:
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()
}
}
有两个选项卡,选择是在主体中引用的,因此更改选择时将调用主体。 TestView正在使用GeometryReader。 当我从“第一个选项卡”切换到“第二个选项卡”时,将再次创建ViewModel,并且从未取消引用。这是意外的。 如果切换100次,我将从SwiftUI内部引用100个ViewModel。
尽管如果我删除GeometryReader,它会按预期工作。
有人经历过吗?有什么解决方法吗? 我只是希望将此ViewModel生存期绑定到TestView生存期。
更新:
XCode 11.3.1 iOS 13.3
答案 0 :(得分:3)
好吧,让我们在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
...
因此,解决方案是从ViewModel
创建TestView
并通过.environmentObject
或通过构造函数参数注入外部实例。
顺便说一句,它不依赖于GeometryReader
。经过Xcode 11.2.1 / iOS 13.2的测试