首页 > 解决方案 > 为什么将 SF 符号放在 UIImage 中,然后放在 SwiftUI Image View 中会导致图像模糊?

问题描述

我正在尝试编写一个采用 UIImage 的公共 init,但我想允许一个普通的、实际的 UIImage 由一张照片(或以其他方式绘制)或使用 SF 符号制成,但我对为什么 SF 感到困惑符号模糊。我错过了什么?

这是我得到的代码:

struct TempUIImageView: View {

    var defaultImage: UIImage = UIImage(systemName: "globe")!

    var defaultImageString: String = "globe"

    var body: some View {
        VStack  {
            Image(uiImage: defaultImage)
                .resizable()
                .scaledToFill()
                .aspectRatio(contentMode: .fit)
            Image(systemName: defaultImageString)
                .resizable()
                .scaledToFill()
                .aspectRatio(contentMode: .fit)
        }
        .padding()
    }
}

我希望在此使用解决方案:

@State private var displayedImage: UIImage?

...

private var displayImage: some View {
    Image(uiImage: displayedImage!)
        .resizable()
        .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
        .scaledToFill()
        .aspectRatio(contentMode: .fit)
        .clipShape(Circle())
        .shadow(radius: 4)
}

但显示图像可能是 UIImage 或 SF 符号。

(强制解包在其他代码中处理,但无论如何这是初步代码)

标签: swiftuiuiimage

解决方案


When you use Image(systemName:) the system draws to the screen using vector graphics, resulting in sharp, un-blurry renderings.

However, UIImage, including, it seems UIImage(systemName:) is a bitmapped image, at a set resolution. If you scale it up (as you're doing in your second block of code), you'll get blurriness, because you're not getting the benefits of the vector graphics.

Using a pattern like the following would allow you to conditionally display a Image(uiImage:) or Image(systemName:) and still use the same set of modifiers for each:

struct ContentView: View {
    @State var displayedImage : UIImage?
    
    var imageToDisplay: Image {
        if let displayedImage = displayedImage {
            return Image(uiImage: displayedImage)
        } else {
            return Image(systemName: "camera.circle")
        }
    }
    
    var body: some View {
        imageToDisplay
            .resizable()
            .scaledToFill()
            .aspectRatio(contentMode: .fit)
            .frame(width: 400, height: 400)
    }
}

推荐阅读