After updating to Xcode 10 I realized that the draw(_ rect: CGRect)
routine of my custom UIView (class derived from UIView) in my application was called with the wrong rect
. Indeed it is always called with rect
being the full frame of the underlying UIView, instead of the rect
being specified by setNeedsDisplay(_ rect: CGRect)
.
Here is a code snippet that can be run as a playground, which at least in my setup shows the erroneous behavior described above in a minimalistic setting:
import Foundation
import UIKit
import PlaygroundSupport
class CustomView: UIView {
override func draw(_ rect: CGRect) {
print("rect = \(rect)")
}
}
let customView = CustomView(frame: CGRect(origin: CGPoint.zero, size: CGSize(width: 200.0, height: 200.0)))
PlaygroundPage.current.liveView = customView
print("test")
customView.setNeedsDisplay(CGRect(origin: CGPoint.zero, size: CGSize(width: 100.0, height: 100.0)))
The output I get is
rect = (0.0, 0.0, 200.0, 200.0)
test
rect = (0.0, 0.0, 200.0, 200.0)
The first printed output for rect is the standard full redraw of the view, but the second one after printing "test" yields the problem. The output there is from redrawing due to calling customView.setNeedsDisplay
before and should be the smaller specified rectangle (0.0, 0.0, 100.0, 100.0)
.
So my obvious questions are:
I tested this in Xcode 9, 10 & 10.1.
The behaviour has definitely changed between iOS 11 and iOS 12 / 12.1
There's no indication in the documentation or header file that this was intentional.
Looks like a bug to me.