Search code examples
swiftswiftuisf-symbols

Function to return modified SF Symbol in SwiftUI


I have written the following function which interprets a given "weather code" value and maps it to an image. Then I modify that image with the .foregroundStyle modifier.

func weatherImage(weatherCode: Int) -> Image {
    switch weatherCode {
    case 0:
        return Image(systemName: "sun.max.fill").foregroundStyle(Color.Orange)
    case 1:
        ...
    case 9: 
        return Image(systemName: "cloud.drizzle.fill").foregroundStyle(Color.white, Color.blue)
    ...
    }
}

The idea is that I could call this function from my Views in manner similar to the following example and render images with uniquely different foregroundStyle modifiers on the fly:

var body: some View {
    VStack {
        weatherImage(weatherCode: 0)
    }
}

However, doing so does not return an Image, but rather some View leading Swift to complain about the return type and it suggest adding as! Image. I have done so and then the code compiles, but at run-time this still leads to a casting error (SwiftUI.ModifiedContent versus SwiftUI.Image) and SIGABRT.

Can my solution be salvaged or is there a better way of handling this programmatically and getting these modified symbols displayed in a View?


Solution

  • You just have to change the function, so it returns a View and not an Image.

    Add a @ViewBuilder at the beginning, remove the returns, remember to provide a default case.

    
        @ViewBuilder
        func weatherImage(weatherCode: Int) -> some View {
            switch weatherCode {
                case 0:
                    Image(systemName: "sun.max.fill").foregroundStyle(.orange)
                case 1:
                    ...
                case 9:
                    Image(systemName: "cloud.drizzle.fill").foregroundStyle(Color.white, Color.blue)
                default:
                    EmptyView()
            }
        }
    

    In the view, just call the function:

    weatherImage(weatherCode: 2)