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

SwiftUI中@State变量首次点击按钮未正确赋值问题

SwiftUI 首次点击按钮无法正确赋值@State变量的问题

问题:为每个CourseClub对象设置按钮,点击时将@State变量watchingClub赋值为当前遍历的对象,再打开详情视图。但首次点击任意按钮时,变量无法正确赋值,详情视图显示初始空值;后续点击按钮正常工作,再次点击首次点击的按钮也能正常赋值。


相关代码

DetailView 代码

var section: KursSection
@EnvironmentObject var vm: TimetableViewModel
var stundenkurse = [CourseStunden]()
@State var showClubPanel = false 
@State var watchingClub = CourseClub(name: "", image: "", sorting: "", dates: [CourseDate(id: "", day: 1, time: Date.now, room: "", startDate: Date.now)])
    
    var body: some View {
        ZStack{
            ScrollView {
                cover
                sections
            }
            .ignoresSafeArea()
            .background()
            .sheet(isPresented: $showClubPanel) {
                CourseDetailView(course: watchingClub)
                    .presentationDetents([.medium, .large])
            }
        }
    }

    var sections: some View {
        VStack(alignment: .leading, spacing: 12){
            ForEach(section.sectionsClub){ stufe in
                Text(stufe.section.uppercased())
                    .font(.footnote.weight(.semibold))
                    .padding(.vertical)
                if(stufe.array.count == 0){
                    Text("Momentan keine Termine für diesen Kurs")
                        .font(.footnote)
                } else {
                    ForEach(stufe.array){ kurs in
                        Button{
                            DispatchQueue.main.async { 
                                self.watchingClub = kurs
                                showClubPanel = true
                            }
                        } label: {
                            HStack{
                                Text(kurs.name)
                                    .padding()
                                    .frame(maxWidth: .infinity)
                                    .background(.ultraThinMaterial)
                                    .cornerRadius(20)
                            }
                        }
                    }
                }
            }

        }
        .frame(maxWidth: .infinity, alignment: .leading)
        .offset(y: 100)
        .padding(.bottom, 200)
        .padding(.horizontal, 20)
    }

CourseClub 结构体代码

struct CourseClub: Identifiable {
    var id = UUID()
    let name: String
    let image: String
    let sorting: String
    var dates = [CourseDate]()
    var sortingInt = 0 
}

主视图导航代码

ScrollView{
            ForEach(sectionData){ section in
                Button{
                    self.section = section
                    shouldNavigate.toggle()
                } label: {
                    KursSectionItem(title: section.title, subtitle: section.subtitle, img: section.img)
                }
            }
            .navigationTitle("Kursübersicht")
        }
        .onAppear(){
            sectionData = [
                KursSection(title: "Erwachsene", subtitle: "Alle Tanzkurse für Erwachsene", img: "//...", sectionsClub: [KursSectionClub(section: "Tanzcards", array: vm.coursesClubErwachsene)]),
            ] 
            // ...
        }

解决方案

问题核心:首次展示sheet时,SwiftUI会提前捕获watchingClub的初始值,后续修改变量时,sheet不会自动更新内容;后续点击正常是因为sheet已存在,状态更新能同步到视图。

推荐修复方案:使用sheet(item:)替代sheet(isPresented:)

利用CourseClub的Identifiable特性,直接绑定可选对象,让sheet根据对象变化自动更新,避免提前捕获值的问题:

  1. 修改watchingClub为可选类型:
@State var watchingClub: CourseClub? // 移除初始空值,改为可选
  1. 替换sheet的绑定方式:
.sheet(item: $watchingClub) { club in
    CourseDetailView(course: club)
        .presentationDetents([.medium, .large])
}
  1. 简化按钮点击逻辑,无需showClubPanel变量:
Button{
    self.watchingClub = kurs // 直接赋值,sheet会自动弹出
} label: {
    // 原label内容保持不变
}

这种方式完全符合SwiftUI的状态管理逻辑,代码更简洁可靠,sheet(item:)会在watchingClub不为nil时自动弹出视图,为nil时自动关闭,且每次都会使用最新的对象创建详情视图。

备选修复方案:强制延迟刷新(不推荐)

若必须保留isPresented方式,可通过延迟刷新确保变量赋值完成后再弹出sheet,但依赖视图刷新时机,稳定性较差:

Button{
    self.watchingClub = kurs
    showClubPanel = false
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
        showClubPanel = true
    }
} label: {
    // 原label内容保持不变
}

内容的提问来源于stack exchange,提问作者Toby

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 16:16:37