SwiftUI:将环境对象传递到工作表会导致更新问题

Kev*_*ers 6 swiftui

如果您想将 传递@EnvironmentObject给以工作表形式呈现的视图,您会注意到每次更新@Published其中的任何属性时都会重新创建该工作表。@EnvironmentObject

演示该问题的最小示例:

import SwiftUI

class Store: ObservableObject {
  @Published var name = "Kevin"
  @Published var age = 38
}

struct ContentView: View {
  @EnvironmentObject private var store: Store
  @State private var showProfile = false

  var body: some View {
    VStack {
      Text("Hello, \(store.name), you're \(store.age) years old")
      Button("Edit profile") {
        self.showProfile = true
      }
    }
    .sheet(isPresented: $showProfile) {
      ProfileView()
        .environmentObject(self.store)
    }
  }
}

struct ProfileView: View {
  @EnvironmentObject private var store: Store
  @ObservedObject private var viewModel = ViewModel()

  var body: some View {
    VStack {
      Text("Hello, \(store.name), you're \(store.age) years old")
      Button("Change age") {
        self.store.age += 1
      }
    }
  }
}

class ViewModel: ObservableObject {
  init() {
    print("HERE")
  }
}
Run Code Online (Sandbox Code Playgroud)

如果运行此代码,您会注意到每次按下工作表中的按钮时都会记录“HERE”,这意味着已重新ViewModel创建。正如您可能想象的那样,这可能是一个巨大的问题,我希望 ViewModel 不会重新创建,而是保留其状态。它在我的应用程序中造成了巨大的问题。

据我所知,我在代码中所做的是将 传递到@EnvironmentObject工作表的正常方法。有没有办法防止ProfileView在发生更改时重新创建Store

nin*_*nes 6

这是因为当状态变量发生变化时视图会被重新创建。在您看来,您将 viewModel 实例化为 ViewModel()。

尝试将观察到的对象作为参数传递,它不会再点击“这里”:

struct ContentView: View {
  @EnvironmentObject private var store: Store
  @State private var showProfile = false
  @ObservedObject private var viewModel = ViewModel()

  var body: some View {
    VStack {
      Text("Hello, \(store.name), you're \(store.age) years old")
      Button("Edit profile") {
        self.showProfile = true
      }
    }
    .sheet(isPresented: $showProfile) {
      ProfileView(viewModel: self.viewModel)
        .environmentObject(self.store)
    }
  }
}

struct ProfileView: View {
  @EnvironmentObject private var store: Store
  @ObservedObject var viewModel: ViewModel

  var body: some View {
    VStack {
      Text("Hello, \(store.name), you're \(store.age) years old")
      Button("Change age") {
        self.store.age += 1
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)