我正在try 创建内部有@StateObject作为数据容器的SwiftUI视图,然而,它依赖于@Environment变量.

当然,我做错了什么,但我找不到有效的解决方案.

这就是我的观点:

struct SomeView: View {
  @EnvironmentObject var router: Router
  @Environment(\.managedObjectContext) var managedObjectContext
  @StateObject var myDataContainer: MyDataContainer
  
  init() {
    let context = managedObjectContext
    _weeklyStatistics = StateObject(wrappedValue: StatisticsWeeklyDataContainer(context: context)) // Exception, as we are trying to access managedObjectContext before init
  }

在初始化期间我无法访问self.managedObjectContext,这导致编译失败.

MyDataContainer依赖于NSManagedObjectContext,它被设置为环境变量:

class MyDataContrainer: ObservableObject {
  @Published var foo: [Date] = []
  
  private let context: NSManagedObjectContext
  
  init(context: NSManagedObjectContext) {
    self.context = context
    print("myDataContainer init")
  }

我想知道,如何正确地解决这些问题?

推荐答案

至少有两种方法可以使用.

  1. 正如 comments 中提到的,你可以使用taskonAppear来更新你的ObservableObject.但是,这意味着该属性必须是Optional,因为它将不存在于init
class MyDataContainer: ObservableObject {
   var context: NSManagedObjectContext?
} 

struct SomeView: View {
  @Environment(\.managedObjectContext) var managedObjectContext
  @StateObject var myDataContainer = MyDataContainer()
  
  var body: some View {
     Text("Hello, world!")
       .onAppear { myDataContainer.context = managedObjectContext }
  }
}

does not需要Optionals的另一种方法是使用包装器视图.

class MyDataContrainer: ObservableObject {
  @Published var foo: [Date] = []
  
  private let context: NSManagedObjectContext
  
  init(context: NSManagedObjectContext) {
    self.context = context
    print("myDataContainer init")
  }
}

struct SomeViewWrapper: View {
  @Environment(\.managedObjectContext) var managedObjectContext

  var body: some View {
     SomeView(context: managedObjectContext)
  }
}

struct SomeView: View {
  @EnvironmentObject var router: Router
  @StateObject var weeklyStatistics: MyDataContainer
  
  init(context: NSManagedObjectContext) {
    _weeklyStatistics = StateObject(wrappedValue: StatisticsWeeklyDataContainer(context: context))
  }

  var body: some View { ... }
}

然后,当然,在以前使用SomeView的地方使用SomeViewWrapper

Swift相关问答推荐

如何取消正在视图修改器中运行的任务

SwiftUI—如何识别单词并获取视觉中的位置

SwiftData查询按日期排序的项的属性数组

依赖于@Environment的init@StateObject

如何在visionOS中定制悬停效果区域

ARRaycast Query和前置摄像头(ARFaceTrackingConfiguration)

正在接收具有不完整数据错误的URL请求

SWIFT`String.Encoding`:`.unicode`vs`.utf16`

为什么这段Swift读写锁代码会导致死锁?

PassthroughSubject 的 AsyncPublisher 值属性未生成所有值

TextField 键入未完成

快速递归:函数与闭包

Swift - 给定一个像 30 的 Int 如何将范围数乘以 7?

Xcode:方法参数的代码完成

Vapor Swift 如何配置客户端连接超时

在 Swift 4 中,如何删除基于块的 KVO 观察者?

将if let与逻辑或运算符一起使用

Swift 中的 PageViewController 当前页面索引

自定义 Google 登录按钮 - iOS

在 Swiftui 中是否有一种简单的方法可以通过捏合来放大图像?