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,
PS I am 100% familiar with the numerous alternate paradigms for drawing a line, thanks.
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.