SwiftUI: Передача environmentObject на лист вызывает проблемы с обновлением - PullRequest
0 голосов
/ 11 февраля 2020

Если вы хотите передать @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")
  }
}

Если вы запустите этот код, вы заметите, что «ЗДЕСЬ» регистрируется при каждом нажатии кнопки на листе, что означает, что ViewModel получил воссоздан. Это может быть огромной проблемой, как вы можете себе представить, я ожидаю, что ViewModel не будет воссоздан, но сохранит свое состояние. Это вызывает огромные проблемы в моем приложении.

Насколько я знаю, то, что я делаю в своем коде, является нормальным способом передачи @EnvironmentObject на лист. Есть ли способ предотвратить воссоздание ProfileView в любое время, когда что-то в Store изменится?

1 Ответ

0 голосов
/ 11 февраля 2020

Это потому, что представление воссоздается при изменении переменной состояния. И в вашем представлении вы создаете экземпляр 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
      }
    }
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...