Come dire alle viste SwiftUI di legarsi a ObservableObjects nidificati


18

Ho una vista SwiftUI che accetta un EnvironmentObject chiamato appModel. Quindi legge il valore appModel.submodel.countnel suo bodymetodo. Mi aspetto che questo associ la mia vista alla proprietà countin submodelmodo che ritorni quando la proprietà si aggiorna, ma questo non sembra accadere.

è un insetto? E in caso contrario, qual è il modo idiomatico di avere viste associate a proprietà nidificate di oggetti di ambiente in SwiftUI?

In particolare, il mio modello è simile a questo ...

class Submodel: ObservableObject {
  @Published var count = 0
}

class AppModel: ObservableObject {
  @Published var submodel: Submodel = Submodel()
}

E la mia vista è simile a questa ...

struct ContentView: View {
  @EnvironmentObject var appModel: AppModel

  var body: some View {
    Text("Count: \(appModel.submodel.count)")
      .onTapGesture {
        self.appModel.submodel.count += 1
      }
  }
}

Quando eseguo l'app e faccio clic sull'etichetta, la countproprietà aumenta ma l'etichetta non si aggiorna.

Posso risolvere questo problema passando appModel.submodelcome proprietà ContentView, ma vorrei evitare di farlo se possibile.


Sto anche progettando la mia app in questo modo. Di solito ho un oggetto App globale nello sviluppo di app precedenti. Qualcun altro pensa che questo progetto di una classe "App" super come variabile d'ambiente diventerà pratica standard? Stavo anche prendendo in considerazione l'utilizzo di più EnvironmentObjects, ma è stato difficile da mantenere.
Michael Ozeryansky,

Risposte:


22

I modelli nidificati non funzionano ancora in SwiftUI, ma potresti fare qualcosa del genere

class Submodel: ObservableObject {
    @Published var count = 0
}

class AppModel: ObservableObject {
    @Published var submodel: Submodel = Submodel()

    var anyCancellable: AnyCancellable? = nil

    init() {
        anyCancellable = submodel.objectWillChange.sink { (_) in
            self.objectWillChange.send()
        }
    } 
}

Fondamentalmente il tuo AppModelcattura l'evento da Submodele lo invia ulteriormente alla vista

Modificare:

Se non hai bisogno SubModeldi essere in classe, puoi provare anche qualcosa del genere:

struct Submodel{
    var count = 0
}

class AppModel: ObservableObject {
    @Published var submodel: Submodel = Submodel()
}

Grazie, questo è utile! Quando dici "I modelli nidificati non funzionano ancora in SwiftUI", sai per certo che sono pianificati?
rjkaplan,

Non ne sono sicuro, ma secondo me dovrebbe funzionare, uso anche qualcosa di simile nel mio proj, quindi se troverò un approccio migliore verrò con una modifica
Sorin Lica,

@SorinLica Dovrebbe Submodelessere il ObservableObject tipo?
Farhan Amjad,

Sta funzionando! Ottima soluzione!
Md Shahed Hossain,

1

Tutti e tre i ViewModel possono comunicare e aggiornare

// First ViewModel
class FirstViewModel: ObservableObject {
var facadeViewModel: FacadeViewModels

facadeViewModel.firstViewModelUpdateSecondViewModel()
}

// Second ViewModel
class SecondViewModel: ObservableObject {

}

// FacadeViewModels Combine Both 

import Combine // so you can update thru nested Observable Objects

class FacadeViewModels: ObservableObject { 
lazy var firstViewModel: FirstViewModel = FirstViewModel(facadeViewModel: self)
  @Published var secondViewModel = secondViewModel()
}

var anyCancellable = Set<AnyCancellable>()

init() {
firstViewModel.objectWillChange.sink {
            self.objectWillChange.send()
        }.store(in: &anyCancellable)

secondViewModel.objectWillChange.sink {
            self.objectWillChange.send()
        }.store(in: &anyCancellable)
}

func firstViewModelUpdateSecondViewModel() {
     //Change something on secondViewModel
secondViewModel
}

Grazie Sorin per la soluzione Combina.


Potresti aggiornare il codice? ha molti errori del compilatore
DevB2F il

-2

Sembra un bug. Quando aggiorno xcode all'ultima versione, funziona correttamente quando si associa a ObservableObjects nidificati


Puoi chiarire su quale versione xcode sei attualmente funzionante? Al momento ho Xcode 11.0 e riscontro questo problema. Ho avuto problemi a ottenere l'aggiornamento alla 11.1, non passerà come l'80% completo.
Michael Ozeryansky,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.