Xcode 9 asset catalog Preserves Vector Data not wo

2019-03-18 09:49发布

I thought the new Preserves Vector Data checkmark in the Xcode 9 asset catalog would finally give us resizing of vector PDF images, but apparently not. Here's my test image seen at two zooms in Preview:

enter image description here

enter image description here

Nice and sharp with lots of zoom, so clearly this is a vector image. But here's what two image views look like in my app:

enter image description here

So where's my vector data? Is this much-desired feature still missing in action? Does it still work only for the automatically generated 2x and 3x images? And if so, what does the Preserve Vector Data checkbox give us that we didn't have already?

4条回答
干净又极端
2楼-- · 2019-03-18 09:54

Edit: Still the same buggy behavior in Xcode 9 GM (9A235)

As of today (Xcode 9 beta 6 9M214v), the image will only be rendered properly (non-blurry) if the UIImageView has at least 3 spacing-related constraints.

eg. spacing to left, spacing to right, spacing to top, and another constraint to define the UIImageView height.

enter image description here

Note also that disabling autolayout completely will make all the UIImageView render incorrectly.

I filled rdar://34306192 (http://www.openradar.me/radar?id=4968083747766272) for this bug.

查看更多
放荡不羁爱自由
3楼-- · 2019-03-18 10:04

In my case (Xcode 9.4.1), with imageView created in Interface Builder - I noticed that when I initially arrive on the screen, the image is blurry. If I then change device orientation, the image becomes crisp. I tried calling different methods manually in viewDidLoad() and here is what I found so far:

This worked:

let image = imageView.image
imageView.image = nil
imageView.image = image

None of these worked:

imageView.layoutSubviews()
imageView.layoutMarginsDidChange()
imageView.setNeedsLayout()
imageView.setNeedsDisplay()
imageView.reloadInputViews()
imageView.updateConstraints()
imageView.contentMode = .center ; imageView.contentMode = .scaleToFill

You should of course extend or subclass UIImageView if you'll be calling it often, like this for example

class UIImageViewWithPreserveVectorDataFix: UIImageView {
    override func awakeFromNib() {
        super.awakeFromNib()
        let image = self.image
        self.image = nil
        self.image = image
    }
}

(and then of course set UIImageViewWithPreserveVectorDataFix as the class in Interface Builder)

查看更多
ら.Afraid
4楼-- · 2019-03-18 10:05

It works, but only if you perform the resizing yourself:

enter image description here

That was achieved in code, like this:

    let im = UIImage(named:"Image")!
    let r = UIGraphicsImageRenderer(size:self.iv2.bounds.size)
    let im2 = r.image {
        _ in
        im.draw(in: self.iv2.bounds)
    }
    self.iv2.image = im2
    self.iv2.contentMode = .center

So UIImageView will rasterize as it scales (e.g. for Aspect Fit), but drawing in code will preserve the vector data.

EDIT New in Xcode 9 beta 5, this now works as expected! In this screen shot, the second image view just does a scale-to-fill, no more. We resize sharply!

enter image description here

查看更多
Fickle 薄情
5楼-- · 2019-03-18 10:05

I had the same issue multiple times with the new Preserves Vector Data.

Super simple solution that worked very well for me:

  1. Never set the UIImageView image property in Interface Builder, just leave it empty.
  2. Set the image value programmatically.

Hope it helps.

查看更多
登录 后发表回答