import SwiftUI import ComposableArchitecture struct MainView: View { let store: StoreOf var onLogout: (() -> Void)? = nil var body: some View { WithViewStore(self.store, observe: { $0 }) { viewStore in InternalMainView(store: store) .onChange(of: viewStore.isLoggedOut) { isLoggedOut in if isLoggedOut { onLogout?() } } } } } // 原 MainView 内容,重命名为 InternalMainView struct InternalMainView: View { let store: StoreOf var body: some View { WithViewStore(self.store, observe: { $0 }) { viewStore in NavigationStack(path: viewStore.binding(get: \.navigationPath, send: MainFeature.Action.navigationPathChanged)) { GeometryReader { geometry in ZStack { // 背景图片 Image("bg") .resizable() .aspectRatio(contentMode: .fill) .frame(maxWidth: .infinity, maxHeight: .infinity) .clipped() .ignoresSafeArea(.all) // 主内容 ZStack { FeedListView(store: store.scope( state: \.feedList, action: \.feedList )) .isHidden(viewStore.selectedTab != .feed) MeView( store: store.scope( state: \.me, action: \.me ) ) .isHidden(viewStore.selectedTab != .other) } .frame(maxWidth: .infinity, maxHeight: .infinity) // 底部导航栏 VStack { Spacer() BottomTabView(selectedTab: viewStore.binding( get: { Tab(rawValue: $0.selectedTab.rawValue) ?? .feed }, send: { MainFeature.Action.selectTab(MainFeature.Tab(rawValue: $0.rawValue) ?? .feed) } )) } .padding(.bottom, geometry.safeAreaInsets.bottom + 60) } } .navigationDestination(for: MainFeature.Destination.self) { destination in switch destination { case .test: TestPushView() case .appSetting: IfLetStore( self.store.scope( state: \.appSettingState, action: MainFeature.Action.appSettingAction ), then: { appSettingStore in WithPerceptionTracking { AppSettingView(store: appSettingStore) } } ) } } } .onAppear { viewStore.send(.onAppear) } } } } struct TestPushView: View { var body: some View { ZStack { Color.blue.ignoresSafeArea() Text("Test Push View") .font(.largeTitle) .foregroundColor(.white) } } }