Swiftui - Як я ініціалізую спостережуваний об'єкт, використовуючи середовищеоб'єкт як параметр?


9

Я не впевнений, чи є це антипатерном у цьому відважному світі SwiftUI, у якому ми живемо, але по суті, у мене є @EnvironmentObject із збереженою базовою інформацією про користувача, яку можуть викликати мої погляди.

У мене також є @ObservedObject, який володіє деякими даними, необхідними для цього представлення даних.

Коли з'явиться подання, я хочу використовувати цей @EnvironmentObject для ініціалізації @ObservedObject:

struct MyCoolView: View { 

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

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

На жаль, я не можу зателефонувати за змінною оточення до моменту ініціалізації:

"Неможливо використовувати член екземпляра" userData "в ініціалізаторі властивостей; ініціалізатори властивостей виконуються до того, як" self "буде доступний."

Я бачу кілька можливих маршрутів вперед, але всі вони відчувають себе хаками. Як я повинен підходити до цього?


Можливо, ви можете спробувати додати користувальницьку initструктуру.
Найєм

Я спробував це і отримав дещо дивну помилку: в Property wrappers are not yet supported on local properties основному його висловлювання я не можу створити @ObservaObject методом init.
snarik

Відповіді:


9

Ось підхід (найпростіший IMO):

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

Це ідеально. MyCoolView насправді був дитиною, який переглядав "будинок", де я оголосив ObservaObject. Дякую!
snarik

Але що робити, якщо ви хочете маніпулювати користувацькими даними всередині ViewObject, не створюючи абсолютно новий ViewObject кожен раз?
BobiSad

0

замість того, щоб створити підпрезгляд, ви можете додати в свій ініціалізатор фіктивних даних, щоб "ViewObject"ви могли викликати його перед тим, як викликати реальний ініціалізатор

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

для запису я його не перевіряв


0

Ось простий шлях до цього:

struct MyCoolView: View {
    @EnvironmentObject var userData: UserData

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

За допомогою цього помічника, який змушує його працювати:

struct Observe<T: ObservableObject, V: View>: View {
    @ObservedObject var obj: T
    let content: (T) -> V
    var body: some View { content(obj) }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.