SwiftUI(macOS):类变量无法触发视图切换,问题排查求助
问题解决:Tab点击后视图不切换的原因及修复
核心问题
你的代码存在状态实例不共享的问题:
MaskingView持有一个MaskingTabProgress实例用于监听视图切换状态MaskingTabControl内部又创建了一个独立的MaskingTabProgress实例
两个实例完全独立,所以TabControl里修改的index根本不会同步到MaskingView的实例上,自然触发不了视图切换。
修复步骤
1. 修改MaskingTabControl,接收外部传入的状态实例
把TabControl内部创建的progress改成从外部传入,确保和上层视图共享同一个实例:
struct MaskingTabControl: View { // 移除内部创建,改为外部传入 @ObservedObject var progress: MaskingTabProgress private let tabText: [String] private let icons: [String] // 更新初始化方法,接收progress实例 public init(items: [String], icons:[String], progress: MaskingTabProgress) { self.tabText = items self.icons = icons self.progress = progress // 可选:如果需要初始化选中索引,可在此设置 // self.progress.index = selectedIndex } var body: some View { ZStack { Color.white .ignoresSafeArea() HStack { ForEach(0..<tabText.count, id: \.self) { index in HStack { Image(systemName: self.icons[index]) .foregroundColor(progress.index == index ? .blue : .black) .font(.system(size: 15, weight: .semibold)) Text(self.tabText[index]) .foregroundColor(progress.index == index ? .blue : .black) .font(.system(size: 15, weight: .semibold)) .padding([.top,.bottom]) }.frame(width: 100) .onTapGesture { progress.index = index } } } }.frame(height: 60) .clipShape(Capsule()) .shadow(color: .gray.opacity(0.5), radius: 5, x: 0, y: 0) } }
2. 在MaskingView中调用TabControl时传入共享的progress实例
修改MaskingView里的MaskingTabControl调用代码,把自身持有的progress传进去:
struct MaskingView: View { @ObservedObject var progress: MaskingTabProgress var body: some View { ZStack { Rectangle() .foregroundColor(AppColor.lightGrayUIBackground) .contentShape(Rectangle()) VStack(spacing: .zero) { MenuBar() if progress.index == 0 { MaskingHomeView() } else { SomeOtherView() } Spacer() // 传入共享的progress实例,移除无用的selectedIndex参数 MaskingTabControl(items: ["Tab One","Tab Two"], icons:["shippingbox.fill","shippingbox.fill"], progress: progress) .padding([.leading, .bottom, .trailing], 15) } } .background(AppColor.lightGrayUIBackground) } }
原理说明
SwiftUI中,@ObservedObject 监听的是具体的实例,只有当同一个实例的@Published属性变化时,所有依赖该实例的视图才会刷新。之前的写法是两个完全独立的实例,所以TabControl里修改的index不会影响到MaskingView的实例,视图自然不会切换。修复后,两个视图共享同一个MaskingTabProgress实例,点击Tab修改index时,MaskingView会感知到变化并重新计算body,实现视图切换。
内容的提问来源于stack exchange,提问作者Eric Dolecki
相关产品推荐
相关产品推荐

