SwiftUI视图数据同步问题:点击按钮后天数计数器不更新
解决SwiftUI中ProgressCardView与BottomSheetView数据不同步问题
问题根源
你的核心问题是两个视图使用了独立的ProgressSettings实例,导致数据无法共享:
ProgressCardView通过@EnvironmentObject获取全局的ProgressSettings实例BottomSheetView却用@StateObject创建了本地独立实例,点击按钮修改的是这个本地实例的dayCount,自然不会同步到ProgressCardView的实例中
解决方案
要让两个视图共享同一个ObservableObject实例,需按以下步骤修改:
1. 修改BottomSheetView,改用EnvironmentObject
移除BottomSheetView中本地创建的ProgressSettings实例,通过@EnvironmentObject获取全局共享实例:
struct BottomSheetView: View { @Environment(\.dismiss) var dismiss // 替换@StateObject为@EnvironmentObject,不再本地创建实例 @EnvironmentObject var settings: ProgressSettings var body: some View { ZStack { Color("background") .edgesIgnoringSafeArea(.all) VStack(alignment: .leading) { HStack { Text("Congratulations!") .padding() .foregroundColor(Color.white) .font(.system(size: 24, weight: .medium)) .italic() Spacer() Text("🎉") .padding() } Text("Congratulations on the successful completion of today's exercise. I'll see you tomorrow. You did great! See you tomorrow!") .padding() .font(.system(size: 14, weight: .regular)) .foregroundColor(Color("grey")) .lineSpacing(5) Divider() .overlay(Color("grey")) VStack { HStack { Spacer() Button(action: { settings.dayCount += 1 dismiss() }) { Spacer() Text("End Session") .frame(width: 230) .padding() .foregroundColor(Color.white) .font(.system(size: 16, weight: .medium)) .italic() .background(Color("red")) .cornerRadius(20) .padding() Spacer() } } } } } } struct BottomSheetView_Previews: PreviewProvider { static var previews: some View { // 预览时传入共享实例 let settings = ProgressSettings() BottomSheetView() .environmentObject(settings) } } }
2. 在父视图中统一注入共享实例
确保你的根视图(比如ContentView)创建唯一的ProgressSettings实例,并通过.environmentObject()传递给所有子视图:
struct ContentView: View { // 在父视图创建唯一的全局实例 @StateObject private var settings = ProgressSettings() @State private var showBottomSheet = false var body: some View { VStack { ProgressCardView() Button("完成今日训练") { showBottomSheet = true } .sheet(isPresented: $showBottomSheet) { BottomSheetView() } } // 将实例注入视图环境,供所有子视图获取 .environmentObject(settings) } }
3. 验证ProgressCardView预览(可选)
你的ProgressCardView预览已经正确使用environmentObject,无需修改,但保持逻辑一致即可:
struct ProgressCardView_Previews: PreviewProvider { static var previews: some View { ProgressCardView() .environmentObject(ProgressSettings()) } }
关键原理
@EnvironmentObject的作用是从视图层级的环境中获取已注入的ObservableObject实例,确保所有使用该对象的视图共享同一个数据源。而@StateObject仅会在当前视图内部创建并持有独立实例,无法跨视图共享数据。
内容的提问来源于stack exchange,提问作者Maksym Skrypka
相关产品推荐
相关产品推荐

