A few years ago, I griped about That Vector Thing, which was the way that Xcode 6 handled PDF vector assets and could not extend them to arbitrary use in UIImages.
Enter WWDC 2017. In Session 201 “What’s New in Cocoa Touch”, Apple described Asset Catalogs with PDF-backed vector images. All you have to do is tick the “Preserve Vector Data” checkbox.
After chatting with some colleagues about whether this would actually work as promised, I dragged up a 29×29 vector PDF image.
And I added it as a 1x image in an asset catalog. Notice the Resizing checkbox to the right. It is normally unchecked by default.
I then built a super-simple single view testbed to test things out.
override func viewDidLoad() { super.viewDidLoad() let imageView = UIImageView() imageView .translatesAutoresizingMaskIntoConstraints = false imageView.contentMode = .scaleAspectFit view.addSubview(imageView) ["H:|[v]|", "V:|[v]|"].forEach { format in NSLayoutConstraint .constraints(withVisualFormat: format, options: .init(rawValue:0), metrics: nil, views: ["v": imageView]).forEach { $0.isActive = true } } let image = UIImage(named: "Biff") imageView.image = image }
Here’s what that 29×29 image looks like running on an iPhone 7+ in the simulator. The 1x image is being rendered on a 3x destination, at a greatly magnified size. Its vector data ensures the image renders without losing detail or clarity. Compare it to the same asset that does not preserve vector data and my original test from 2014:
Click above to see full size screenshot originals. Below is a comparison shot from the simulator at the largest size.
I expect there are minor performance hits in scaling and rendering the vector image compared to loading a standard PNG or JPEG, but I didn’t get around to measuring the costs.
If you like my write-ups, please consider buying a book.
20 Comments
Very nice. Thanks for the heads-up Erica.
I was really hoping Apple would expose a native SVG drawing API with iOS 11, but it doesn’t seem to be happening. It’s a great shame, because the existing SVG projects on GitHub are a mixed bag; no-one project is complete. (Which is mostly due to SVG being a diabolical format, IMO.)
Anyway, thanks again.
As an author of one of the incomplete SVG projects, yeah, SVG would be a more flexible choice than PDF. If for nothing else, that I could imagine a mechanism to dynamically restyle artwork via CSS, so you could have a pink dog with a dashed grey outline (in the example in the blog entry).
So, yeah, I’d like to add CSS support to my project, but SVG fonts seem like a massive waste of time to implement, and the various special-effects might be troublesome. Then there is new things that might end up in SVG like variable width lines. How am I supposed to efficiently implement variable width lines in Core Graphics?
Glenn, thank you for all your work! It’s greatly appreciated. SVG parsing is awfully complex, and just plain hard. It really is a format designed by a committee of engineers who subscribe to the Kitchen Sink School of Format Design. (Just look at feColorMatrix or feMorphology! It’s a file format, API from hell.) I’m so glad there are people like you out there who have done so much of the hard work. Cheers.
Glen,
I currently use your package. It works very well. As you say it is incomplete but still very valuable. Your system aside from CSS allows the global line color to be set so I am able to draw items in different colors on demand.
Thanks for you package.
@David thanks. Yeah, it’s surprising how much redundant artwork you can avoid just by allowing a single color to be dynamically set. Of course, being text, SVGs can be manipulated pretty easily by replacing keywords by searching; for those cases when you’ve got several styles to change.
I’ve got to make time to start my CSS project though. That’ll be awesome.
David, thanks for the encouragement.
One other advantage of SVG is with the platforms argument. Any artwork I generate can be used for the web app version of my app, and used in a responsive, dynamically resized design with lightweight downloads, assuming the SVGs themselves are well formed. On my own, extremely simple, web page, I just dropped in the same SVGs I use in my apps and they get resized to fit the users screen beautifully.
For vector based animation that works in a web view, here is my recent Mac app – an open-source WebKit-based SVG editor named macSVG at http://macsvg.org and GitHub.
macSVG looks great! It’s very good of you to OS it. Regarding SVG 2, I think it’s time that W3C were taken out behind the woodshed.
IMO, we really need a json-based replacement. An SVG 3 Lite, without all the tedious over-engineered baggage from W3C. Something super-simple, straight-forward that doesn’t try to do everything.
I haven’t look at Sketch’s new format deeply at all, but maybe, just maybe it’s an answer? Or perhaps a subset of it.
Looking more at macSVG. It really is an accomplished piece of work. Well done.
Great to see advances in this area. Still, though, nothing beats PaintCode IMHO. I’ve used it for years and avoided the pain in the xcassets of supporting multiple resolutions with image files.
Scott, I agree that PaintCode is very good. The trouble comes when you need a lot of images; suddenly, that becomes a huge issue, particularly in Swift and the state of Xcode 8. sourcekitservice just _dies_. I had to switch to SVG, with a lot of mark-up and hand-parsing. The advantage of doing that is you can treat your art like other images, and load the on-demand, instead of having them compiled in to your binary.
Hi David, agreed, SourceKit crashes are pretty common when working with large StyleKits in <= Xcode 8. I've also run into lengthy compile times when working large StyleKits. Breaking them up into separate StyleKits helps. PaintCode is also great for creating interactive and dynamic controls and other wholly-contained UI elements.
If you use wide color then beware: I tried this with wide color display P3 vector images and they get clipped to sRGB if you try to use PDF instead of PNG. It looks like for wide color you should either rasterize to PNG or draw them in code with PaintCode and use the new asset catalogue color assets or UIColor(displayP3Red:green:blue:alpha:) for your P3 colors (#colorLiteral is always sRGB even if you use the color picker to select P3).
Erica Thanks for your article !
MacSVG looks awesome. If single color artwork is acceptable, another option can be to create a custom font. I did that for my Mac app and it works great. I use a font editor called Glyphs Mini which was about $40. (The full version of Glyphs is around $300, but is not necessary for icon fonts.)
Jim, that’s a great idea. Will investigate.
Doesn’t seem like you can use PDF images for app icons – pity.
I’ve noticed this doesn’t seem to work if you set an image via storyboards. Only seems to work if you set the image and frame in code.
Can anyone confirm this?
My sample project: https://github.com/micnguyen/vector_assets/tree/master
Radar: https://openradar.appspot.com/radar?id=6095650269691904
This is great. Vector support in UIImage is something I have wanted for a long time. Thanks for sharing!
Are the vector graphics bundled with your app and resized dynamically when displayed or are they just used to create PNGs at compile-time and those are bundled in which is how it worked before?