1

Using a wrapper allows us to pass EnvironmentObject down into ObservedObject. Nice approach..

But what if you want to manipulate the userData inside ViewObject without an entirely new ViewObject being created every time?

In my app entire view is recreated after I change EnvironmentObject and i don't know how to avoid this.

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)")
    }
}
eugene_prg
  • 948
  • 2
  • 12
  • 25

1 Answers1

2

But what if you want to manipulate the userData inside ViewObject without an entirely new ViewObject being created every time?

Here is a demo of possible solution - make viewObject as StateObject (this will make it persistent through view refresh) and inject userData into it

Tested with Xcode 12.1 / iOS 14.1

class UserData: ObservableObject {
    @Published var UID = "1"
}

class ViewObject: ObservableObject {
    var userData: UserData?
    @Published var myCoolProperty = "Hello"
}

struct MyCoolView: View {
    @EnvironmentObject var userData: UserData

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

struct MyCoolInternalView: View {
    @StateObject private var viewObject = ViewObject()

    init(_ userData: UserData) {
        self.viewObject.userData = userData
    }

    var body: some View {
            Text("\(self.viewObject.myCoolProperty)")
    }
}
Asperi
  • 228,894
  • 20
  • 464
  • 690
  • Thanks! But in my version ViewObject is initialized by passing userData.UID so i can build the view based on data fetched from network or db. In yours I can't use UserData's properties at init as ViewObject is initialised without params and when it is created - userData property is not yet set. Let's say i put the content of my init(id: ) into some execute() function. How do I launch it properly to generate my view? Text().onAppear ? – eugene_prg Dec 05 '20 at 16:59
  • Not sure I understood what do you mean - you asked *to manipulate the userData inside ViewObject*. No? If you don't have userData inside ViewObject what do you meant then by *manipulate*? – Asperi Dec 05 '20 at 17:03