SwiftUI替换单例为@Environment后崩溃:ExperimentManager未在环境中设置的问题求助
SwiftUI替换单例为@Environment后崩溃:ExperimentManager未在环境中设置的问题求助
我最近在把App里的单例实现替换成SwiftUI的@Environment来管理各类Manager依赖,结果一运行就崩溃了,抛出的致命错误是:
Thread 1: Fatal error: ExperimentManager not set in environment.
我已经做了一些排查:在App结构体的init里初始化experimentManager的位置加了断点,断点确实在崩溃前被命中了,说明这个实例是成功创建出来的,但就是没正确注入到环境中?
下面是我的相关代码,麻烦大家帮忙看看问题出在哪,或者给点调试的方向,非常感谢!
环境键定义代码
import SwiftUI // MARK: - TaskManager private struct TaskManagerKey: EnvironmentKey { static let defaultValue: TaskManager = { fatalError("TaskManager not set in environment.") }() } extension EnvironmentValues { var taskManager: TaskManager { get { self[TaskManagerKey.self] } set { self[TaskManagerKey.self] = newValue } } } // MARK: - AssessmentManager private struct AssessmentManagerKey: EnvironmentKey { static let defaultValue: AssessmentManager = { fatalError("AssessmentManager not set in environment.") }() } extension EnvironmentValues { var assessmentManager: AssessmentManager { get { self[AssessmentManagerKey.self] } set { self[AssessmentManagerKey.self] = newValue } } } // MARK: - WorkoutManager private struct WorkoutManagerKey: EnvironmentKey { static let defaultValue: WorkoutManager = { fatalError("WorkoutManager not set in environment.") }() } extension EnvironmentValues { var workoutManager: WorkoutManager { get { self[WorkoutManagerKey.self] } set { self[WorkoutManagerKey.self] = newValue } } } // MARK: - BlueprintManager private struct BlueprintManagerKey: EnvironmentKey { static let defaultValue: BlueprintManager = { fatalError("BlueprintManager not set in environment.") }() } extension EnvironmentValues { var blueprintManager: BlueprintManager { get { self[BlueprintManagerKey.self] } set { self[BlueprintManagerKey.self] = newValue } } } // MARK: - GoalManager private struct GoalManagerKey: EnvironmentKey { static let defaultValue: GoalManager = { fatalError("GoalManager not set in environment.") }() } extension EnvironmentValues { var goalManager: GoalManager { get { self[GoalManagerKey.self] } set { self[GoalManagerKey.self] = newValue } } } // MARK: - ImageManager private struct ImageManagerKey: EnvironmentKey { static let defaultValue: ImageManager = { fatalError("ImageManager not set in environment.") }() } extension EnvironmentValues { var imageManager: ImageManager { get { self[ImageManagerKey.self] } set { self[ImageManagerKey.self] = newValue } } } // MARK: - ServiceManager private struct ServiceManagerKey: EnvironmentKey { static let defaultValue: ServiceManager = { fatalError("ServiceManager not set in environment.") }() } extension EnvironmentValues { var serviceManager: ServiceManager { get { self[ServiceManagerKey.self] } set { self[ServiceManagerKey.self] = newValue } } } // MARK: - SuggestedGoalsDataSource private struct SuggestedGoalsDataSourceKey: EnvironmentKey { static let defaultValue: SuggestedGoalsDataSource = { fatalError("SuggestedGoalsDataSource not set in environment.") }() } extension EnvironmentValues { var suggestedGoalsDataSource: SuggestedGoalsDataSource { get { self[SuggestedGoalsDataSourceKey.self] } set { self[SuggestedGoalsDataSourceKey.self] = newValue } } } // MARK: - ExperimentManager private struct ExperimentManagerKey: EnvironmentKey { static let defaultValue: ExperimentManager = { fatalError("ExperimentManager not set in environment.") }() } extension EnvironmentValues { var experimentManager: ExperimentManager { get { self[ExperimentManagerKey.self] } set { self[ExperimentManagerKey.self] = newValue } } }
App结构体代码
import PhotosUI import Supabase import SwiftData import SwiftUI @main struct ImproveMyselfApp: App { @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate @StateObject private var accountManager: AccountManager @StateObject private var blueprintManager: BlueprintManager private var taskManager: TaskManager private var workoutManager: WorkoutManager private var assessmentManager: AssessmentManager private var goalManager: GoalManager private var imageManager: ImageManager private var serviceManager: ServiceManager private var suggestedGoalsDataSource: SuggestedGoalsDataSource private var experimentManager: ExperimentManager @State private var hasCompletedOnboarding = UserDefaults.standard.bool( forKey: "HasCompletedOnboarding" ) @State private var isInitialized = false @State private var errorMessage: String? let userDataContainer: ModelContainer init() { do { userDataContainer = try ModelContainer( for: UserData.self, BeforePhoto.self, Blueprint.self, InspirationImage.self, QuoteFileUsage1.self, LifeAreaRating1.self, MentalState.self, SuggestedGoalChoices.self, SuggestedGoalPairEntity.self, TaskItem.self, TaskCompletion.self, ShareItem.self, Suggestion.self, Comment.self, Vote.self, Tag.self, WorkoutPlan.self, WorkoutExercise.self, Subtask.self ) // 这里初始化了各类Manager,包括experimentManager,断点命中此处 accountManager = AccountManager() blueprintManager = BlueprintManager(container: userDataContainer) taskManager = TaskManager(container: userDataContainer) workoutManager = WorkoutManager(container: userDataContainer) assessmentManager = AssessmentManager(container: userDataContainer) goalManager = GoalManager(container: userDataContainer) imageManager = ImageManager() serviceManager = ServiceManager() suggestedGoalsDataSource = SuggestedGoalsDataSource() experimentManager = ExperimentManager() } catch { fatalError("Failed to initialize ModelContainer: \(error)") } } var body: some Scene { WindowGroup { if hasCompletedOnboarding { MainTabView() } else { OnboardingView() } .environment(\.modelContext, userDataContainer.mainContext) .environmentObject(accountManager) .environmentObject(blueprintManager) // 怀疑这里漏了注入其他Manager到环境中 } } }
我现在最怀疑的点是:在App的body里,我只给accountManager和blueprintManager加了.environmentObject,但其他Manager(包括experimentManager)根本没通过.environment(\.experimentManager, experimentManager)这种方式注入到环境中?或者是不是某个子View在App还没完成环境注入的时候就提前读取了experimentManager?
麻烦大家帮忙分析下,谢谢啦!
内容来源于stack exchange
相关产品推荐
相关产品推荐

