You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 01:52:41