'How to create a gray UIImage from SF Symbol?

I have a model called Contact with an optional property called imageData of type Data, and a computed property called image of type UIImage that tries to initiate an UIImage from the imageData property, and if imageData is nil then it initiates an UIImage from SF Symbols.

I am using the computed property image to show the image in a List by calling Image(uiImage: contact.image).

In my case, the imageData property is nil.

I want the color to be gray, but it is black, and I want to color the image inside the computed property.

https://github.com/fawzialrifai/Contacts2

import SwiftUI

struct Contact: Identifiable {
    var id = UUID()
    var name: String
    var imageData: Data?
    var image: UIImage {
        if let imageData = imageData {
            return UIImage(data: imageData)!
        } else {
            return UIImage(systemName: "person.crop.circle.fill")!.withTintColor(.gray, renderingMode: .alwaysOriginal)
        }
    }
}

struct ContactList: View {
    var contacts = [Contact(name: "Fawzi")]
    var body: some View {
        List(contacts) { contact in
            HStack(alignment: .center) {
                Image(uiImage: contact.image)
                    .resizable()
                    .scaledToFill()
                    .frame(width: 45, height: 45)
                    .clipShape(Circle())
                Text(contact.name)
            }
            .padding(.vertical, 8)
        }
    }
}


Solution 1:[1]

return Image(systemName: "person.crop.circle.fill")
     .renderingMode(.template)
     .foregroundColor(.gray)

Solution 2:[2]

In case you want to change the tint color for the image you should use render mode alwaysTemplate

Try updating the following line.

return UIImage(systemName: "person.crop.circle.fill")!.withTintColor(.gray, renderingMode: .alwaysTemplate)

Solution 3:[3]

here's another approach, if you want to use Image.foregroundColor(.gray)

var avatarImage : Image {
    if let imageData = imageData, let image = UIImage(data: imageData) {
        return Image(uiImage: image)
    } else {
        return Image(systemName: "person.crop.circle.fill")
               .foregroundColor(.gray) as! Image
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Priya Talreja
Solution 2 Abdul Momen
Solution 3 Andrei G.