为何SwiftUI子视图View2的@State参数未随父视图更新?
为什么View2用@State接收父视图参数,父视图更新后View2的Text不刷新?
我在SwiftUI里做了个测试场景:父视图ContentView有个@State修饰的text变量,View1通过@Binding接收这个text,View2用@State接收。点击View1的按钮修改text后,只有ContentView的Text组件更新,View2的Text完全没变化。但打印日志显示,View1和View2都用新值"View 1 Text"重新调用了初始化方法,把View2改成@Binding后,它的Text就会正常跟着刷新了,这是怎么回事?
核心原因解析
- @State是子视图的局部独立状态:View2里的
@State var text是它自己的局部状态,初始化时只是把父视图的text值复制了一份存到自己的状态容器里,之后就和父视图的text没有任何关联了。当父视图的text更新导致ContentView的body刷新、重新创建View2实例时,SwiftUI会保留View2之前的@State局部值,忽略初始化时传入的新值——这是SwiftUI为了避免父视图刷新导致子视图局部状态丢失的设计逻辑。 - @Binding是父视图状态的引用:View1的
@Binding本质是对父视图@State变量的引用,相当于和父视图共享同一个数据源。修改@Binding的值直接就是修改父视图的@State,父视图刷新后,所有依赖这个@State的视图(包括ContentView、View1,以及改成@Binding后的View2)都会读取最新的数据源值,自然同步更新。
示例代码
ContentView.swift
import SwiftUI struct ContentView: View { @State var showView1: Bool = false @State var showView2: Bool = false @State var text: String = "Hello World" init() { print("init ContentView") } var body: some View { VStack { Image(systemName: "globe") .imageScale(.large) .foregroundColor(.accentColor) Text("\(text)") HStack { if showView1 { View1($text) } if showView2 { View2(text) } } .border(.black) HStack { Button("View1") { showView1.toggle() } Button("View2") { showView2.toggle() } } } .padding() } }
View1.swift
struct View1: View { @Binding var text: String init(_ text: Binding<String>) { self._text = text print("init View1 \(self.text)") } var body: some View { Button("Click") { print("Click view1 button") self.text = "View 1 Text" } } }
View2.swift
struct View2: View { @State var text: String init(_ text: String) { self.text = text print("init View2 \(self.text)") } var body: some View { VStack { Button("Click") { print("Click view2 button") } Text("view2 text : \(text)") } } }
内容的提问来源于stack exchange,提问作者Xenius
相关产品推荐
相关产品推荐

