You Don't Need UIImage

The Image view provides a way to initialize it using UIKit’s UIImage. This was used to work-around some early issues with Swift UI which prevented custom symbols to be scaled and colored.

Here’s how we display, color and scale a built-in image:

Image(systemName: "heart.circle")
  .resizable()
  .aspectRatio(contentMode: .fit)
  .foregroundColor(.red)

And here’s how we used to display a custom SVG image using UIImage as intermediary:

  Image(uiImage: UIImage(named: "heart.circle.custom")!)
    .resizable() // Dynamic sizing
    .aspectRatio(contentMode: .fit)
    .foregroundColor(.red)

Except that it would not take the foreground color and the scaling would be done by resampling a bitmap producing a low resolution result.

To work around these issue we would wrap the image in a dummy Button view, which would take care of the color. Then we would have to use a font size to scale the vector image in high resolution, like so:

Button(action: {}) { // Dummy button
  Image(uiImage: UIImage(named: "heart.circle.custom")!
    .withConfiguration(
        // Fixed size in points
        UIImage.SymbolConfiguration(pointSize: 100)
    )
  )
}
.foregroundColor(.red) // Color applied to button

But this still poses the problem of having to specify a static size. The solution is quite simple: avoid the use of UIImage and use the standard fixed method.

Image("heart.circle.custom")
  .resizable()
  .aspectRatio(contentMode: .fit)
  .foregroundColor(.red)

Works like a charm!

See below for a result comparison of each of the methods described on this post.

Ways of displaying custom symbols