为啥 SwiftUI @main App 中的实例化不创建 EnvironmentObject?
Posted
技术标签:
【中文标题】为啥 SwiftUI @main App 中的实例化不创建 EnvironmentObject?【英文标题】:Why Doesn't Instantiation In SwiftUI @main App Not Create An EnvironmentObject?为什么 SwiftUI @main App 中的实例化不创建 EnvironmentObject? 【发布时间】:2021-07-09 18:07:56 【问题描述】:我正在使用 SwiftUI 和 @EnvironmentObjects。我正在使用 SwiftUI 应用程序生命周期。在这个文件中,我为 ListingRepository 创建了一个 @StateObjects 并使用 .envrionmentObjects() 将它附加到 ContentView()。
struct MyApp: App
// @EnvironmentObjects
@StateObject private var listingRepository = ListingRepository()
var body: some Scene
WindowGroup
ContentView()
.environmentObject(listingRepository)
我的假设是我现在可以通过使用 @EnvironmentObject 包装器来访问 ListingRepository。但是,似乎我必须再次实例化它。下面是我的列表视图模型。我的第一次尝试如下所示。
class MarketplaceViewModel: ObservableObject
@EnvironmentObject var listingRepository: ListingRepository
@Published var listingRowViewModels = [ListingRowViewModel]()
private var cancellables = Set<AnyCancellable>()
init()
listingRepository
.$listings
.receive(on: RunLoop.main)
.map listings in
listings.map listing in
ListingRowViewModel(listing: listing)
.assign(to: \.listingRowViewModels, on: self)
.store(in: &cancellables)
这引发了以下错误。
致命错误:未找到 ListingRepository 类型的 ObservableObject。一种 ListingRepository 的 View.environmentObject(_:) 可能作为 此视图的祖先。
第二个选项使用@Published 并修复错误。
class MarketplaceViewModel: ObservableObject
@Published var listingRepository = ListingRepository()
@Published var listingRowViewModels = [ListingRowViewModel]()
private var cancellables = Set<AnyCancellable>()
init()
listingRepository
.$listings
.receive(on: RunLoop.main)
.map listings in
listings.map listing in
ListingRowViewModel(listing: listing)
.assign(to: \.listingRowViewModels, on: self)
.store(in: &cancellables)
我的问题如下。
-
有必要像我一样实例化两次吗?
为什么@main App 中的实例化不起作用?
【问题讨论】:
【参考方案1】:在您的@main App 中,您应该像这样定义您的环境对象:
struct MyApp: App
// @EnvironmentObjects
var listingRepository = ListingRepository()
var body: some Scene
WindowGroup
ContentView()
.environmentObject(listingRepository)
然后将 ListingRepository 定义为:
class ListingRepository: ObservableObject
@Published var ...
@Published var ...
// Your code here
不要在 MarketPlaceViewModel 中将 ListingRepository 重新声明为 EnvironmentObject。
但是,请注意,将您的 ListingRepository 设为可观察对象并通过 MarketPlaceViewModel 从您的视图中访问该对象是不明智的。如果 MarketPlaceViewModel 用于填充应用中的视图,并且 MarketPlaceViewModel 从 ListingRepository 获取数据,则应将 MarketPlaceViewModel 设为 EnvironmentObject 而不是 ListingRepository。
SwiftUI 中的事情是您希望 EnvironmentObject 将更改发布到应用程序中的多个视图,以便这些视图可以重建自己。如果您在模型和视图之间使用视图模型,则视图模型应该是 EnvironmentObject。
【讨论】:
非常感谢您的回复。我正在关注谷歌推荐的教程。我会进一步调查。 你可能想看看这个教程youtube.com/watch?v=stSB04C4iS4或者这个youtube.com/watch?v=1QcekWFK2d8以上是关于为啥 SwiftUI @main App 中的实例化不创建 EnvironmentObject?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我不能访问这个数组 ForEach 循环中的数据? SwiftUI
如何仅使用 SwiftUI 从@main App 访问 NSWindow?
SwiftUI - HealthKit 中的 DispatchQueue.main.async
SwiftUI - HealthKit 中的 DispatchQueue.main.async