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

时间:2020-02-10 22:36:45

标签: 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")
  }
}

如果运行此代码,您会发现每按一次表单中的按钮,就会记录一次“ HERE”,这意味着重新创建了ViewModel。您可能会想象到,这可能是一个巨大的问题,我希望不会重新创建ViewModel,而是保留其状态。这在我的应用程序中引起了巨大的问题。

据我所知,我在代码中执行的操作是将@EnvironmentObject传递到工作表的常规方法。有没有一种方法可以防止ProfileView中的任何更改重新创建Store

2 个答案:

答案 0 :(得分:1)

这是因为当状态变量更改时,会重新创建视图。然后在您的视图中将viewModel实例化为ViewModel()。

尝试将观察到的对象作为参数传递,它将不再命中“ HERE”:

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
      }
    }
  }
}

答案 1 :(得分:0)

一篇关于这个问题的非常好的文章can be found her