SwiftUI环境对象报错求助:找不到ViewModel类型的ObservableObject
问题分析与解决
错误原因
- SwiftUI View是值类型:你调用
rootView.environmentObject(HomeView.ViewModel())时,会返回一个新的View实例,而非修改原有的rootView。但传给super.init的仍是最初未注入环境对象的HomeView,导致HomeView渲染时找不到ViewModel实例,触发崩溃。 - 错误访问EnvironmentObject:试图通过
rootView.viewModel直接读取环境对象,不符合SwiftUI设计——@EnvironmentObject实例由SwiftUI环境管理,外部不能通过View实例直接获取。
修复方案
核心思路
- 初始化
UIHostingController时,直接创建已注入environmentObject的HomeView实例 - 在
HomeViewController中持有ViewModel实例,后续更新属性直接操作该实例,而非通过View对象
修改后的代码
HomeViewController
class HomeViewController: UIHostingController<HomeView> { // MARK: - Public Properties var topThreePublicUsers = PassthroughSubject<[ExternalUser], Never>() // MARK: - Private Properties private var cancellables: Set<AnyCancellable> = [] // 持有ViewModel实例,方便外部更新 private let viewModel: HomeView.ViewModel // MARK: - Initializer init() { // 先创建ViewModel实例 viewModel = HomeView.ViewModel() // 创建带有环境对象的rootView let rootView = HomeView().environmentObject(viewModel) super.init(rootView: rootView) topThreePublicUsers .receive(on: DispatchQueue.main) // 直接操作持有的viewModel实例 .assign(to: \.topThreePublicUsers, on: viewModel) .store(in:&cancellables) } @MainActor required dynamic init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } func pushPublicLeaderBoard(viewController: UIViewController) { if let viewController = viewController as? UIHostingController<PublicLeaderboardView> { // 直接操作持有的viewModel实例 viewModel.publicLeaderboard = viewController.rootView } } }
HomeView(保持原结构,补充缺失属性)
struct HomeView: View { // MARK: - Environment @EnvironmentObject var viewModel: ViewModel // MARK: - View Model class ViewModel: ObservableObject { @Published var profileView: ProfileView? // 补充需要的@Published属性,确保属性变化能触发View更新 @Published var topThreePublicUsers: [ExternalUser] = [] @Published var publicLeaderboard: PublicLeaderboardView? } // MARK: - Body var body: some View { viewModel.profileView } }
额外提示
- 所有需要触发View更新的属性,必须在ViewModel中声明为
@Published - 永远不要直接访问View的
@EnvironmentObject或@StateObject属性,这类实例由SwiftUI生命周期管理,外部操作通过持有ViewModel实例完成即可
内容的提问来源于stack exchange,提问作者WikipediaBrown
相关产品推荐
相关产品推荐

