SwiftUI - ObservableObject создается несколько раз

Я создал ObservableObject в представлении.

@ObservedObject var selectionModel = FilterSelectionModel()

Я поставил точку останова внутри FilterSelectionModelс initфункция и вызывается несколько раз. Поскольку это представление является частьюNavigationLink, Я понимаю, что он создается тогда и вместе с ним selectionModel. Когда я перехожу к представлению, selectionModel создается снова.

В этом же представлении у меня есть "вспомогательное представление", в котором я передаю selectionModel как EnvironmentObject так что подвид может изменить это.

AddFilterScreen().environmentObject(self.selectionModel)

Когда подвид закрывается, selectionModel создается еще раз, и внесенные в него изменения исчезают.

Интересное примечание: на самом верхнем уровне находитсяNavigationView. ЕСЛИ я добавлю

.navigationViewStyle(StackNavigationViewStyle())

к этому NavigationView, мои изменения selectionModel исчезают. НО если я не добавлюnavigationStyle, изменения selectionModel, сделанные во вспомогательном представлении, остаются!! (Но мне не нужен разделенный вид навигации, мне нужен составной вид навигации)

В обоих случаях - с или без navigationStyle, selectionModel создается несколько раз. Я не могу понять, как все это должно работать надежно.

2 ответа

Последние обновления SwiftUI принесли решение этой проблемы. (iOS 14 и более поздние версии)

это то, что мы должны использовать вместо , но только там, где этот объект создается, а не везде в подвидах, где мы передаем один и тот же объект.

Например-

      class User: ObservableObject {
    var name = "mohit"
}


struct ContentView: View {
  @StateObject var user = User()

  var body: some View {
    VStack {
      Text("name: \(user.name)")
      NameCount(user: self.user)
   }
  }
}


struct NameCount: View {
  @ObservedObject var user

  var body: some View {
    Text("count: \(user.name.count)")
  }
}

В приведенном выше примере только представление, ответственное ( ContentView ) за создание этого объекта, аннотирует объект с помощью @StateObjectи все другие представления ( NameCount ), которые совместно используют объект. @ObservedObject.

При таком подходе всякий раз, когда ваше родительское представление ( ContentView ) воссоздается, объект не будет воссоздан, и он сохранит свое @State , в то время как ваши дочерние представления просто observingк тому же Userобъект не должен заботиться о своем воссоздании.

Вы можете создать экземпляр наблюдаемого объекта в методе init, таким образом вы сможете сохранить его значение, иначе значение не исчезнет.

Создайте экземпляр этого способа в файле представления.

@ObservedObject var selectionModel : FilterSelectionModel

init() {
   selectionModel = FilterSelectionModel(value : "value to be saved from disappearing")
}

Создайте экземпляр этого способа в файле viewModel.

class FilterSelectionModel : ObservableObject {

  @Published var value : String

  init(value : String) {
     self.value = value
  }

}

Это обходной путь, который я нашел, но все же метод init вызывается несколько раз, и я не добился успеха с этой проблемой.

Чтобы остановить множественную инициализацию ViewModels, поскольку представление объявлено в представлении навигации, а SwiftUI использует структуру, которая является типом значения, поэтому в конечном итоге они инициализируются до представления представления, поэтому вы можете преобразовать это представление в LazyView, поэтому что он будет инициализирован только тогда, когда представление будет представлено или показано.

// Use this to delay instantiation when using `NavigationLink`, etc...
struct LazyView<Content: View>: View {
    var content: () -> Content
    var body: some View {
       self.content()
    }
}

Вы можете назвать это так...

 NavigationLink(destination: LazyView { ViewTobePresented() }) 
Другие вопросы по тегам