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

为何在View2修改authState时,View1的onChange(of:)未触发?

问题原因分析

你遇到的问题核心在于视图的生命周期管理:
MainTabView通过ZStack+switch切换页面时,当选中View2,View1会被直接从视图树中移除并销毁;切回View1时,View1是全新创建的实例。这种情况下:

  • 在View2中修改authState后,切回View1时,新的View1实例初始化时拿到的就是修改后的authState值,而onChange(of:)仅监听当前视图实例生命周期内的属性变化,自然不会触发回调。

解决方案

方案一:保留View1的存活状态

通过透明度和可点击性控制视图显示,让View1和View2始终存在于视图树中,避免被销毁:

struct MainTabView: View {
  @State private var selectedTab = 0

  var body: some View {
    ZStack {
      View1()
        .opacity(selectedTab == 0 ? 1 : 0)
        .allowsHitTesting(selectedTab == 0)
      
      View2()
        .opacity(selectedTab == 1 ? 1 : 0)
        .allowsHitTesting(selectedTab == 1)
    }
    .safeAreaInset(edge: .bottom) {
      HStack {
        Button("1") { selectedTab = 0 }
        Button("2") { selectedTab = 1 }
      }
      .buttonStyle(.borderedProminent)
    }
  }
}

这种方式下,View1始终存活,当authState变化时,onChange(of:)会正常触发。

方案二:在视图初始化时订阅状态变化

利用Task订阅authState的数据流,即使View1被重建,也能在视图出现时监听后续的状态变化:

struct View1: View {
  @Environment(AuthManager.self) var authManager

  var body: some View {
    NavigationStack {
      VStack {
        Text("\(authManager.authState)")
      }
      .task {
        // 订阅authState的所有变化
        for await _ in authManager.$authState.values {
          print("Changed")
        }
      }
    }
  }
}

如果需要在视图出现时立即检查一次状态,可以在task开头先执行一次逻辑:

.task {
  print("Current state: \(authManager.authState)")
  for await _ in authManager.$authState.values {
    print("Changed")
  }
}

方案三:在AuthManager层面添加状态回调

通过在AuthManager中定义闭包,统一处理状态变化通知,避免依赖视图生命周期:

@Observable class AuthManager {
  var authState: AuthState = .signedOut {
    didSet {
      onAuthStateChange?(authState)
    }
  }
  // 定义状态变化回调
  var onAuthStateChange: ((AuthState) -> Void)?
  
  // ...其他代码
}

然后在View1中绑定回调(注意弱引用避免内存泄漏):

struct View1: View {
  @Environment(AuthManager.self) var authManager

  var body: some View {
    NavigationStack {
      VStack {
        Text("\(authManager.authState)")
      }
      .onAppear {
        authManager.onAuthStateChange = { [weak self] _ in
          guard let self = self else { return }
          print("Changed")
        }
      }
      .onDisappear {
        authManager.onAuthStateChange = nil
      }
    }
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.02 07:07:27