UIImageView image does not update visibly when ima

2019-02-24 12:34发布

问题:

I have a UIImageView whose user interaction is true and to which I have given a tap gesture recognizer, whose action handler is as follows:

@IBAction func tap(_ sender:UITapGestureRecognizer) {
    let iv = sender.view as! UIImageView
    let im = iv.image!
    let im2 = UIGraphicsImageRenderer(size:im.size).image { _ in
        UIColor.red.setFill()
        UIBezierPath(rect: CGRect(origin:.zero, size:im.size)).fill()
    }
    iv.image = im2
}

I expect the image displayed, when I tap the image view, to be replaced by a solid red image. This works fine on my High Sierra machine running Xcode 9.4. But on my Sierra MacBook running Xcode 9.2, nothing visibly happens.

It's weird. By pausing in the debugger, I can see that the new image is being constructed correctly:

The image is being replaced, but the image view isn't being redrawn. Adding calls like setNeedsDisplay does nothing.

Moreover, if I then proceed to replace the image view's image with a different image, I see the red image!

    iv.image = im2
    delay(0.5) {
        iv.image = im // causes im2 to appear!
    }

Some sort of behind-the-scenes caching is evidently causing the image view to get behind in its display by one image.

Can anyone shed light on this? It's presumably a bug in iOS itself, and perhaps in 9.2 specifically; how would one work around it? (Obviously one could substitute another image view wholesale, but that wouldn't tell us what's going on with the caching.)

回答1:

This seems to be a workaround:

iv.image = im2
delay(0.05) {
    iv.image = nil
    iv.image = im2
}

But what a horror... Omitting any of those assignments, or reducing the delay to zero (e.g. by calling DispatchQueue.main.async instead), causes the workaround to fail.