uikitswift5drawrect

Is the only way to have draw#rect redraw, in cases where you want that done on any size change, indeed with setNeedsDisplay in layoutSubviews?


Say you're drawing a line in draw#rect in some view,

override func draw(_ rect: CGRect) {
    guard let c = UIGraphicsGetCurrentContext() else { return }
    c.move(to:  CGPoint(x: 13, y: 13 ) )
    c.addLine(to: CGPoint(x: 69, y: 69 ) )
    }
    
    c.setLineWidth(1.0 / UIScreen.main.scale)
    ...
}

imagine that for example the user can change the size of the view (perhaps via a pinch).

For contreteness imagine for some reason the UIView changes in size from 100.100 to 300.000

As we know, when that happens it will scale that short line which it drew on the root layer. So if the view goes to 300.300, the line will triple in thickness, and indeed get fuzzy, since it is a transform blow-up.

Of course, other elements in the view, whether text added by constraints, layer shapes etc, will "expand logically" rather than literally zooming.

Now in some cases, depending on the logic of the app, you may want the line to be redrawn by draw#rect, all the time, ie as you resize the UIView bigger and smaller.

In such cases, what I have always done is this,

override func layoutSubviews() {
    super.layoutSubviews()
    setNeedsDisplay()
    someOtherStuff.path = calculation().cgPath
    someLabel.text = String(bounds.width / 13)
}

I just do setNeedsDisplay() every layout pass.

This works perfectly well(as far as I know!) but my question is simple:

is there some other better, simpler, more "built-in" way to do this?

For all I know, there may well be a "drawOnFrameChange#rect" type of call that I don't know about, or there may be a flag / combination of flags on views I don't know about. (There are so many weeds in UIView, like clearsContextBeforeDrawing, that interact in subtle ways.)

I am always astounded at what I do not know about UIKit, am I missing something basic here?

The question,

Is the only way to have draw#rect continuously redraw, in cases where you want that done on any size change, indeed by continually calling setNeedsDisplay, say in layoutSubviews?

PS I am 100% familiar with the numerous alternate paradigms for drawing a line, thanks.


Solution

  • If I understand correctly, you can set contentMode to .redraw.

    someView.contentMode = .redraw
    

    From the documentation:

    The option to redisplay the view when the bounds change by invoking the setNeedsDisplay() method.