Swiftui - Come posso inizializzare un oggetto osservato usando un oggetto environment come parametro?


9

Non sono sicuro che si tratti di un antipasto in questo nuovo mondo coraggioso di SwiftUI in cui viviamo, ma essenzialmente ho un @EnvironmentObject con alcune informazioni utente di base salvate in esso che le mie opinioni possono chiamare.

Ho anche un @ObservedObject che possiede alcuni dati richiesti per questa vista.

Quando appare la vista, voglio usare @EnvironmentObject per inizializzare @ObservedObject:

struct MyCoolView: View { 

    @EnvironmentObject userData: UserData
    @ObservedObject var viewObject: ViewObject = ViewObject(id: self.userData.UID)  

    var body: some View { 
            Text("\(self.viewObject.myCoolProperty)")
    } 
}

Sfortunatamente non posso chiamare self sulla variabile d'ambiente fino a dopo l'inizializzazione:

"Impossibile utilizzare il membro di istanza 'userData' all'interno dell'inizializzatore di proprietà; gli inizializzatori di proprietà vengono eseguiti prima che sia disponibile 'self'."

Vedo alcuni possibili percorsi in avanti, ma sembrano tutti degli hack. Come dovrei avvicinarmi a questo?


Forse puoi provare ad aggiungere un'abitudine initalla struttura.
nayem,

L'ho provato e ho Property wrappers are not yet supported on local properties riscontrato un errore un po 'strano: sostanzialmente dice che non posso creare un oggetto @ObservedOb in un metodo init.
Snarik,

Risposte:


9

Ecco l'approccio (l'IMO più semplice):

struct MyCoolView: View {
    @EnvironmentObject var userData: UserData

    var body: some View {
        MyCoolInternalView(ViewObject(id: self.userData.UID))
    }
}

struct MyCoolInternalView: View {
    @EnvironmentObject var userData: UserData
    @ObservedObject var viewObject: ViewObject

    init(_ viewObject: ViewObject) {
        self.viewObject = viewObject
    }

    var body: some View {
            Text("\(self.viewObject.myCoolProperty)")
    }
}

Questo è perfetto. MyCoolView era in realtà un figlio di una vista 'home' in cui ho dichiarato ObservedObject. Grazie!
Snarik,

Ma cosa succede se si desidera manipolare i dati utente all'interno di ViewObject senza che ogni volta venga creato un ViewObject completamente nuovo?
BobiSad,

0

invece di creare una sottoview puoi aggiungere un inizializzatore fittizio al tuo in "ViewObject"modo da poterlo chiamare prima di chiamare l'inizializzatore reale

struct MyCoolView: View { 

    @EnvironmentObject userData: UserData
    @ObservedObject var viewObject: ViewObject

    init() {
        viewObject = ViewObject()
        defer {
            viewObject = ViewObject(id: self.userData.UID)
        }
    }

    var body: some View { 
            Text("\(self.viewObject.myCoolProperty)")
    } 
}

per la cronaca non l'ho provato


0

Ecco un modo semplice per farlo:

struct MyCoolView: View {
    @EnvironmentObject var userData: UserData

    var body: some View {
        Observe(obj: ViewObject(id: userData.UID)) { viewObject in
             Text("\(viewObject.myCoolProperty)")
        }
    }
}

Con questo aiuto che lo fa funzionare:

struct Observe<T: ObservableObject, V: View>: View {
    @ObservedObject var obj: T
    let content: (T) -> V
    var body: some View { content(obj) }
}
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.