Xcode 11 PDF image assets "Preserve Vector Data" not working in SwiftUI?
Asked Answered
H

2

20

I'm trying to use vector-based PDF images using "Single-Scale" in an app I'm working on using SwiftUI in Xcode 11, but the image always looks blurry when I scale it up in size.

I had no trouble with this in UIKit in Xcode 11. I created a dummy app with 2 scenes, both displaying the same vector image. I created the first scene in a storyboard, then used a HostingViewController to embed an identical scene made in SwiftUI. When I ran the app, the first scene (UIKit) displayed a crisp, non blurry image. The second (SwiftUI) scene however, was blurry and didn't appear to be using vector data, despite using the same source image asset.

I was able to "work around" this by creating a UIImage with the vector image, then using this UIImage extension to resize the UIImage before it's passed into Image. However, the size I enter in the resized(to:) method makes no difference at runtime, so I also have to add .frame(w:,h:) to image in 'var body' to make it show the correct size.

let uiImage = UIImage(named: "Logo-vector")!
var image: Image {
        Image(uiImage: uiImage.resized(to: CGSize(width: 500, height: 500)))
            .resizable()
}

var body: some View {
        NavigationView {
            VStack(alignment: .center, spacing: 8) {
                Spacer()
                Text("Logo vector SwiftUI")
                image
                    .frame(width: 240, height: 216)
                ...
                }
                ...
            }
        }
}

extension UIImage {
    func resized(to size: CGSize) -> UIImage {
        return UIGraphicsImageRenderer(size: size).image { _ in
            draw(in: CGRect(origin: .zero, size: size))
        }
    }
}

The image is clear and properly resized at runtime with this workaround, but it feels like a bit of a hack.

I've looked everywhere online for a different solution or anyone else having this issue specifically with SwiftUI, but haven't found anything at all.

Has anyone else had this issue or does anyone have a better solution?

Hellenist answered 17/9, 2019 at 8:0 Comment(4)
Yes, your hacks works for me. But I do not understand why this stop to work I used in Assets.xcasstets always PDF + "Preserve Vector Graphics" + "Single Scale" and It worked. In Xcode 11.3.1, iOS 13.x it seems to does not work correctly. Maybe it is something connected to view refreshing in SwiftUI as there are many issues with refresh handlingClapp
@MichałZiobro I don't use SwiftUI and it's broken too.Fango
Did you ever figure this out? Seeing the same behavior in Xcode 12 beta 1 when using an image in a widget.Followthrough
Does this answer your question? Why do PDFs resized in SwiftUI getting sharp edges?Triarchy
S
4

try enabling "IPreserve Vector Data" on each pdf image asset (select image in "Assets.xcassets" folder, then in "Attributes inspector > Image Set > Resizing")

Spier answered 13/12, 2019 at 15:40 Comment(0)
I
1

I put together a cross-platform framework called ResizableVector which performs the same resizing method.

extension PlatformImage {
    func resized(to size: CGSize) -> PlatformImage {
        return GraphicsImageRenderer(size: size).image { _ in
            self.draw(in: CGRect(origin: .zero, size: size))
        }
    }
}

Where PlatformImage is simply a typealias for UIImage or NSImage and GraphicsImageRenderer is a typealias for the UIGraphicsImageRenderer or MacGraphicsImageRenderer.

The framework provides a SwiftUI View named ResizableVector to use in place of Image. It can also respect the original aspect ratio, if desired.

You can add this using SPM - check it out on GitHub: https://github.com/Matt54/ResizableVector

Insnare answered 27/2, 2022 at 16:57 Comment(1)
This should really be the accepted answer, because this just works!Mckinnon

© 2022 - 2024 — McMap. All rights reserved.