SwiftUI报错:未找到MakeMyOwnListViewModel类型的ObservableObject
错误解决与ObservableObject/EnvironmentObject用法指南
错误原因
你遇到的No ObservableObject of type MakeMyOwnListViewModel found错误,核心是:使用@EnvironmentObject的View必须从祖先View的环境中获取对应ViewModel实例,但你的代码中,当从MainView导航到MakeMyOwnListView时,MainView所在的WindowGroup并没有注入MakeMyOwnListViewModel,导致子View找不到实例。
代码修正步骤
1. 修正App中的ViewModel声明与注入
在ManifestationMenuApp中,用@StateObject创建唯一的MakeMyOwnListViewModel实例,然后在所有需要的环境中注入这个实例(而不是每次新建):
import SwiftUI @main struct ManifestationMenuApp: App { @AppStorage("isOnboarding") var isOnboarding: Bool = true // 创建全局唯一的ViewModel实例,生命周期与App绑定 @StateObject var listViewModel: MakeMyOwnListViewModel = MakeMyOwnListViewModel() var body: some Scene { WindowGroup { if isOnboarding { OnboardingView() } else { MainView() .environmentObject(MenuListFriendshipViewModel()) .environmentObject(MenuListWealthViewModel()) .environmentObject(MenuListEducationViewModel()) .environmentObject(MenuListCareerViewModel()) .environmentObject(MenuListFamilyViewModel()) .environmentObject(MenuListHealthViewModel()) .environmentObject(MenuListSpiritualityViewModel()) // 注入共享的MakeMyOwnListViewModel到MainView环境 .environmentObject(listViewModel) } } WindowGroup { NavigationView { MakeMyOwnListView() } .navigationViewStyle(StackNavigationViewStyle()) // 复用同一个实例,确保数据同步 .environmentObject(listViewModel) } } }
2. 保持MakeMyOwnListView的正确声明
MakeMyOwnListView中继续使用@EnvironmentObject,不要改成@ObservableObject——因为这个View是共享父级的ViewModel实例,而非自己创建:
struct MakeMyOwnListView: View { @EnvironmentObject var listViewModel: MakeMyOwnListViewModel // 其余代码保持不变 }
ObservableObject系列属性的核心用法
@ObservableObject
- 用于标记遵循
ObservableObject协议的类,在View中声明时,表示该View拥有这个ViewModel的独立实例。 - 缺点:每个使用
@ObservableObject的View会创建自己的实例,数据无法跨View共享;View销毁时,ViewModel也会被销毁。 - 适用场景:仅当前View使用的ViewModel,不需要共享数据的情况。
@StateObject
- SwiftUI 2.0+引入,用于在App/父View级别创建唯一且生命周期绑定的ViewModel实例。
- 特点:实例只会被创建一次,宿主(App/View)存在时,实例不会被意外销毁,是实现全局/跨View共享数据的正确方式。
- 适用场景:需要多个View共享数据的ViewModel,比如你的
MakeMyOwnListViewModel。
@EnvironmentObject
- 用于在子View中获取祖先View通过
.environmentObject(_:)注入的ViewModel实例,无需手动传递参数。 - 要求:必须在当前View的某个祖先View(包括App级的WindowGroup)上调用
.environmentObject(_:)注入对应实例,否则会触发找不到实例的致命错误。 - 适用场景:跨多层View共享同一个ViewModel实例的情况,比如从
MainView跳转的MakeMyOwnListView、MakeMyOwnAddView等。
常见误区
- 不要在每个需要ViewModel的View中用
@ObservableObject创建实例,会导致数据割裂、实例重复。 - 不要用
@EnvironmentObject在App或父View中声明ViewModel,它只用于子View获取实例。 - 注入
environmentObject时,必须确保是同一个实例(比如用@StateObject创建的实例),否则多个窗口/View的数据无法同步。
内容的提问来源于stack exchange,提问作者Kraig Kistler
相关产品推荐
相关产品推荐

