iosswiftuibezierpathibdesignable

UIBezierPath draws differently in storyboard and simulator


I'm creating a custom IBDesignable control and I want to draw a set of squares in there. I have a draw(_ rect:) method which does the following:

override func draw(_ rect: CGRect) {

        // ... skipped ...
        
        for i in 0 ..< 7 {
            for j in 0 ... 6 {

                let x = Double(i) * (cellSize + space)
                let y = Double(j) * (cellSize + space)
                
                let rectangle = CGRect(x: x, y: y, width: cellSize, height: cellSize)
                let face = UIBezierPath(roundedRect: rectangle, cornerRadius: CGFloat(0))

                face.fill()
            }
        }
    }

This works just fine when I add the component into interface builder and I can see the squares. But when I run it in the simulator it draws rectangles but not squares:

enter image description here

This seems quite weird as width is equal to height. It works same way even if I draw with lines:

let face = UIBezierPath()
face.move(to: CGPoint(x: x, y: y))
face.addLine(to: CGPoint(x: x + cellSize, y: y))
face.addLine(to: CGPoint(x: x + cellSize, y: y + cellSize))
face.addLine(to: CGPoint(x: x, y: y + cellSize))
face.close()

or if I use regular not round corner rectangle:

let face = UIBezierPath(rect: rectangle)

Any ideas what could be wrong?


Solution

  • The problem is timing. The view is being drawn using squares, but then the interface is laid out and the view height is made a little smaller or its width is made a little larger. The drawing is cached — you have not set the view to be redrawn when its bounds change — so the drawing is now slightly distorted, as if a scale transform had been applied to it with a different horizontal value from the vertical value. Hence the squares are no longer square.