SwiftUI技术问题:Sheet弹出视图接收值未更新,如何正确传值?
SwiftUI Sheet传递值异常的问题分析与修复
问题原因
你遇到的问题是SwiftUI状态更新时机导致的:当在同一个按钮闭包里连续修改firstName和presentSheet两个@State属性时,SwiftUI会将这两次状态变更合并为一次视图刷新。而sheet(isPresented:)的内容是在presentSheet变为true的瞬间捕获当前的firstName值——此时firstName的更新还没完成视图树的同步,所以Sheet拿到的还是旧值"Fred"。
解决方法
改用sheet(item:)绑定可选数据源的方式,这种方式能确保Sheet捕获到最新的状态值,具体代码修改如下:
方案一:扩展String遵循Identifiable
struct ContentView: View { @State private var selectedName: String? = nil var body: some View { Button { selectedName = "Jane" } label: { Text("go to sheet") } .sheet(item: $selectedName) { name in SubView(theName: name) .presentationDetents([.medium]) } } } extension String: Identifiable { public var id: String { self } } struct SubView: View { let theName: String var body: some View { Text("theName = \(theName)") } }
方案二:自定义可识别数据模型(更规范)
struct NameModel: Identifiable { let id = UUID() let value: String } struct ContentView: View { @State private var selectedName: NameModel? = nil var body: some View { Button { selectedName = NameModel(value: "Jane") } label: { Text("go to sheet") } .sheet(item: $selectedName) { model in SubView(theName: model.value) .presentationDetents([.medium]) } } } struct SubView: View { let theName: String var body: some View { Text("theName = \(theName)") } }
原理说明
sheet(isPresented:)更适合不需要传递动态变化数据的场景,它的内容是在触发呈现时捕获当前状态快照。而sheet(item:)直接绑定数据源的可选值,当你更新这个数据源并将其设为非空时,Sheet会直接使用最新的数据源值,从根本上避免了状态同步的时机问题。
内容的提问来源于stack exchange,提问作者Foul Plumbing
相关产品推荐
相关产品推荐

