imageswiftui

SwiftUI ImageRenderer not working with colors from Assets catalogue


I've come along a problem that seems to be a bug. But may be I am omitting something in respect to iOS 18.

Description: After clicking the button, I render some view as an image and store it as Data for later:

struct ContentView: View {
    
    @State private var data:Data?
    
    private var img:Image {
        if let data {
            return Image(uiImage: UIImage(data: data) ?? UIImage())
        }else{
            return Image(systemName: "xmark.circle.fill")
        }
    }
    
    var body: some View {
        VStack {
            TestView()
            Button("Test") {
                let ren=ImageRenderer(content: TestView())
                if let data=ren.uiImage?.pngData() {
                    self.data=data
                }
            }
            img
                .resizable()
        }
    }
    
}

struct TestView:View {
    
    var body: some View {
        VStack {
            ZStack {
                Rectangle()
                    .fill(Color.red)
                Text("TEST")
            }
            
            ZStack {
                Rectangle()
                    .fill(Color.test)
                Text("TEST 2")
            }
        }
        
    }
}

Color.test was defined in the Assets catalogue. This worked fine on versions prior to iOS/iPadOS 18.

So before clicking the button, one would see this: enter image description here

clicking on the button, the view would show this: enter image description here

with the upgrade, it seems as if colors from the assets catalogue are not available and the result looks like this: enter image description here

Rectangle with TEST 2 has no color.

Any ideas?


Solution

  • This works as expected on macOS, so this is most likely a bug. It seems like resolving a ColorResource in an ImageRenderer is just a bit broken on iOS 18. Color.init(_:bundle:) also appears to have the same problem.

    A workaround is to convert from a UIColor, because apparently UIColor.init(named:) is not broken. Assuming you have generated extensions for UIColor, you can write

    .fill(Color(uiColor: .test))