我面临着一个非常奇怪的问题,我不知道如何解决这个问题。
Text
中有一个TabView
和VStack
。现在的问题是,当我尝试根据某些 Text
属性设置 @State
的文本时。 SwiftUI 刷新所有视图,包括在 TabView
中添加的页面也被重新创建。我正在分享一个示例代码片段,这将有助于解释。
我的主要观点:
struct TestingView: View {
@State private var someText: String = "Hello"
@State private var page: Int = 0
var body: some View {
VStack {
Text(someText + " \(page)")
TabView(selection: $page) {
ViewOne()
.tag(0)
ViewTwo()
.tag(1)
ViewThree()
.tag(2)
}
.tabViewStyle(.page(indexDisplayMode: .never))
}
}
}
选项卡视图页面:
struct ViewOne: View {
init() {
print("View one init")
}
var body: some View {
Text("View one")
}
}
struct ViewTwo: View {
init() {
print("View two init")
}
var body: some View {
Text("View two")
}
}
struct ViewThree: View {
init() {
print("View three init")
}
var body: some View {
Text("View three")
}
}
现在,如果你在
TabView
上滑动,它会导致 $page
发生变化,最终影响 Text
。当 Text
内的文本更改时,所有视图都会重新创建。
我的问题:
我尝试为
Text
制作单独的视图并绑定 TestingView
中的值,但结果是相同的。
SwiftUI 的工作原理如下:
每当视图的状态发生变化时,SwiftUI 就会将此更改安排为主线程上的内部更新任务。 状态更改由对 State 属性、Environment 变量和对象的更改、objectWillChange 发布者或对 Observable 对象的非私有属性更改来触发。
布局任务首先创建一个新的视图实例,记住视图在SwiftUI中是值类型,然后比较状态改变是否需要新的布局过程。
如果需要新的布局过程,则旧视图实例将被新视图实例替换,并检索新实例的 body 属性。
在您的示例中,通过更改
TestingView
状态属性来更改 page
的状态。这会导致在下一个布局阶段触发新的布局过程,即在 body
上调用 TestingView
属性。
这也会调用 init
、ViewOne
和 ViewTwo
的 ViewThree
方法,因为这就是您的 body
实现的作用。
然而,SwiftUI 通过比较发现这些子视图没有改变,因此不会调用它们的布局方法。结果,不必要生成的视图被丢弃。
以下是您应该了解并牢记的有关 SwiftUI 的一些基本事项:
let _ = Self._printChanges()