1

I have a SwiftUI view with a few text fields at the top, and I am trying to dynamically change the color of these. The best option I have found so far is to keep a @State variable that holds an array of colors corresponding to the colors of each of the text fields. However, I am trying to update this @State from another class, which doesn't seem possible.

To try to fix this, I was looking at using an ObservableObject with a @Published array that works the same way as the previously mentioned array of colors: the class that would do the changing of colors would have this array within it somewhere, and would update the array with new colors; the View would then have an @ObservedObject, and each Text would reference the @ObservedObject.

Here is my issue though: the function that I want to be able to change the colors is static. Swift will not let me make a @Published static var, so this static function can't change the array that is the focus of the @ObservedObject. Is there another way to set up something similar to @State or @ObservedObject that would allow me to dynamically update colors, that is also accessible from a static function?

Here is a rough idea of what I am hoping to set up:

The view that holds the Text elements:

struct TextView: View {
    @ObservedObject var colorChange = ColorChangingClass()
    
    var body: some View {
        HStack {
            Text("Text Field 1")
                .padding()
                .background(Color.gray)
                .foregroundColor(colorChange.colorArray[0])
                .cornerRadius(5.0)
            Text("Text Field 2")
                .padding()
                .background(Color.gray)
                .foregroundColor(colorChange.colorArray[1])
                .cornerRadius(5.0)
            Text("Text Field 3")
                .padding()
                .background(Color.gray)
                .foregroundColor(colorChange.colorArray[2])
                .cornerRadius(5.0)
        }
    }
}

The class with the static function that alters the colors:

class ColorChangingClass: ObservableObject {
    static func changingColors() {
        // I want to be able to change the colors from here
    }
    
    // Swift won't let me make this static
    @Published var colorArray: [Color] = [Color.blue, Color.red, Color.green]
}

The placement of the colorArray is flexible so long as I can access it from this static function, this just seemed to be the closest thing to a solution that I could find, but obviously it doesn't quite work.

Charlie
  • 136
  • 1
  • 8
  • Is the array of colors fixed, as in, do you need to change the colors within the array, or just select a different element from the array to return a color? – Yrb Apr 07 '22 at 13:08
  • I was hoping to change the colors within the array and have that translate to a color change of the text in the view, but if there was a way to dynamically select a different element from the array to change the color of the text I would be perfectly fine with that. – Charlie Apr 07 '22 at 14:56
  • When you used the `State` variable, how did you dynamically change the color? – Yrb Apr 07 '22 at 15:17
  • I wasn't actually able to make that work, since I want to be able to change the `State` variable from other classes, which doesn't seem possible. Ideally I would just be able to have other classes directly change the variable, and that would prompt the view to update with the new color. – Charlie Apr 07 '22 at 21:10
  • Were you able to get it to work from within the class? The reason I am asking, is I am not sure how you wanted the mechanism to work for the change, and there is nothing in the posted code that changes anything. If you could edit the question and post the old code it would be helpful. – Yrb Apr 07 '22 at 21:22
  • I was not able to get any version of this working yet, since I need something outside of the class to be able to edit the colors of the view. I would ideally just be able to have something like `colorArray[0] = Color.green` in `changingColors()`, but that doesn't work because the function is static. – Charlie Apr 07 '22 at 23:22

1 Answers1

1

Dynamically changing colors with @State or @ObservableObject using static functions in Swift

Simple answer: this is not possible.

Simple reason: @Published works only on instance var and not static


As there is missing context I just asume you want to change the colors from different views. If thats the reason for implementing the function as static there is a workaround.

Instantiate your ColorChangingClass at the top most View that uses it as a @StateObject. Hand it down to the child views via .environmentObject().

If you provide more context there could be other possible solutions too.

burnsi
  • 6,194
  • 13
  • 17
  • 27
  • Thanks for the info! I ended up finding a way to change the `changingColors()` function to not be static so I was able to use a `ObservableObject` and `ObservedObject` setup, but I'm pretty sure your suggestion would have also worked. – Charlie Apr 08 '22 at 04:14