Search code examples
swiftui

How to pass an enviromentObject to a UIViewRepresentable's Coordinator?


I would like to pass an environment object to a UIViewRepresentable like this:

DrawingUI()
  .environmentObject(toolbarModel)

This toolbarModel has a property called selectedUIColor that I need the UIViewRepresentable to update.

Then I have this:

struct DrawingUI: UIViewRepresentable {
  @EnvironmentObject private var toolbarModel:ToolbarModel

...

let coordinator = Coordinator(!!!!!)

class Coordinator: NSObject, PKToolPickerObserver {
// for some reason I have to have this property
// again because I did not find a way to set the
// same property outside the coordinator
private var toolbarModel:ToolbarModel

private var selectedUIColor:UIColor {
  didSet {
    toolbarModel.selectedUIColor = selectedUIColor
  }
}

init(_ toolbarModel:ToolbarModel) {
  self.toolbarModel = toolbarModel
}

...

func makeCoordinator() -> PencilKitSwiftUI.Coordinator {
  return Coordinator(!!!!!)
}

My problem is: What do I put on the !!!!! parts?


Solution

  • In SwiftUI you are supposed to only pass in what the View/UIViewRepresentable structs need to do their job (not whole objects). For read/write access you need @Binding var so try changing it to:

    
    struct DrawingUI: UIViewRepresentable {
        @Binding var selectedUIColor: UIColor // this can change every time the representable is init by parent View's body
    
        // think of this like a diff to update the view and coordinator with all the changed lets/vars above
        func updateUIView(uiView: YourViewType, context: Context) {
            context.coordinator.selectionDidChange = nil
            if uiView.selectedUIColor != selectedUIColor {
                uiView.selectedUIColor = selectedUIColor
            }
            context.coordinator.selectionDidChange { selection in 
                selectedUIColor = selection
            }
        }
         
        func makeCoordinator() -> PencilKitSwiftUI.Coordinator {
          return Coordinator() // no params
        }
    
        func makeUIView ...