更新AppStorage状态后导航与Tab选中丢失,主题切换页面跳转问题
问题描述
我希望实现App配色方案切换功能,但在ThemeView中点击主题样式时,页面会自动退回SettingsView,且Tab会重新选中Home页。请问如何在切换配色方案后停留在ThemeView中?
相关代码
AppTabView.swift
public enum ThemeStyle: Int, CaseIterable { case automatic case light case dark } extension View { @ViewBuilder func themeStyle(_ themeStyle: ThemeStyle) -> some View { switch themeStyle { case .automatic: self case .light: preferredColorScheme(.light) case .dark: preferredColorScheme(.dark) } } } struct AppTabView: View { @AppStorage(StorageKeys.themeStyle) private var themeStyle: ThemeStyle = .automatic var body: some View { TabView(selection: $tabItem) { Text("First Tab") .tabItem { Label("Home", systemImage: .house) } NavigationView { SettingsView() } .tabItem { Label("Settings", systemImage: .gearshapeFill) } } .themeStyle(themeStyle) .toggleStyle(SwitchToggleStyle(tint: .accentColor)) } }
SettingsView.swift
struct SettingsView: View { var body: some View { List { Section { NavigationLink { ThemeView() } label: { Label("TITLE_THEME", systemImage: .circleLefthalfFill) } } .navigationTitle("TITLE_SETTINGS") .navigationBarTitleDisplayMode(.inline) } }
ThemeView.swift
struct ThemeView: View { @AppStorage(StorageKeys.themeStyle) private var themeStyle: ThemeStyle = .automatic @ViewBuilder private func text(_ themeStyle: ThemeStyle) -> some View { switch themeStyle { case .automatic: Text("TITLE_THEME_AUTOMATIC") case .light: Text("TITLE_THEME_LIGHT") case .dark: Text("TITLE_THEME_DARK") } } @ViewBuilder private func image(_ themeStyle: ThemeStyle) -> some View { switch themeStyle { case .automatic: Image(systemName: .circleLefthalfFill) case .light: Image(systemName: .sunMax) case .dark: Image(systemName: .moon) } } var body: some View { List { ForEach(ThemeStyle.allCases, id: \.rawValue) { value in Button { themeStyle = value } label: { HStack { Label { text(value) .foregroundColor(.label) } icon: { image(value) } if themeStyle == value { Spacer() Image(systemName: .checkmark) } } } } } .navigationTitle("TITLE_THEME") .navigationBarTitleDisplayMode(.inline) } }
解决方案
问题核心是切换主题时,AppTabView因themeStyle变化触发整体重绘,嵌套在Tab项内的NavigationView会被重新初始化,导致导航栈重置、Tab选中状态丢失。
1. 调整NavigationView层级
将NavigationView从Settings的Tab项中移出,包裹整个TabView,避免主题切换时导航栈被重置:
struct AppTabView: View { @AppStorage(StorageKeys.themeStyle) private var themeStyle: ThemeStyle = .automatic @State private var tabItem: Int = 1 // 初始化选中Settings页,可按需调整 var body: some View { NavigationView { TabView(selection: $tabItem) { Text("First Tab") .tabItem { Label("Home", systemImage: .house) } .tag(0) SettingsView() .tabItem { Label("Settings", systemImage: .gearshapeFill) } .tag(1) } .navigationTitle(tabItem == 0 ? "Home" : "Settings") .navigationBarTitleDisplayMode(.inline) } .themeStyle(themeStyle) .toggleStyle(SwitchToggleStyle(tint: .accentColor)) } }
2. 移除SettingsView内的嵌套NavigationView
由于外层已有NavigationView,SettingsView无需再嵌套:
struct SettingsView: View { var body: some View { List { Section { NavigationLink { ThemeView() } label: { Label("TITLE_THEME", systemImage: .circleLefthalfFill) } } } .navigationTitle("TITLE_SETTINGS") .navigationBarTitleDisplayMode(.inline) } }
3. 可选:持久化Tab选中状态
若希望重启App后保留上次选中的Tab,可将tabItem改用@AppStorage存储:
@AppStorage("selectedTab") private var tabItem: Int = 1
修改完成后,切换主题时ThemeView会保持当前页面状态,不会退回SettingsView,Tab选中状态也能稳定保留。
内容的提问来源于stack exchange,提问作者Xiaolong.Jin
相关产品推荐
相关产品推荐

