2

I'm drawing a cut-out hole in CAShapeLayer using UIBezierPath, this is the code I have so far:

let view = UIView(
 frame: CGRect(origin: .zero, size: CGSize(width: 500.0, height: 500.0))
)
view.backgroundColor = .clear
let shapeLayer = CAShapeLayer()
shapeLayer.frame = view.bounds
shapeLayer.fillColor = UIColor.systemMint.cgColor
let mainPath = UIBezierPath(
 roundedRect: CGRect(
 origin: CGPoint(x: 50.0, y: 50.0), size: CGSize(width: 400.0, height: 400.0)
 ),
 cornerRadius: 10.0
)
let cutOutArc = UIBezierPath()
cutOutArc.addArc(
 withCenter: CGPoint(x: 50.0, y: 250.0),
 radius: 50.0,
 startAngle: .pi / 2.0,
 endAngle: .pi + .pi / 2.0,
 clockwise: false
)
cutOutArc.addLine(to: CGPoint(x: 50.0, y: 200.0))
cutOutArc.close()
mainPath.append(cutOutArc)
shapeLayer.fillRule = .evenOdd
shapeLayer.path = mainPath.cgPath
view.layer.insertSublayer(shapeLayer, at: 0)

(The code is simplified and adapted to use in Playground.)

The code results in this shape (looks exactly as I need):

A square shape with a half-arc cut-out hole in the centre of the left edge

What I can't figure out how to do is adding a corner radius to the cut-out arc (where the red arrows in the image below point), say, of 4.0 points. I've played with pretty random options for a couple days now with no meaningful result. I tried to ask AI, and it couldn't figure out it either (it just kept on producing broken code really).

A square shape with a half-arc cut-out hole in the centre of the left edge, and red arrows pointing to the place, where I need to add corner radius

Does anyone know how to do it? Any guidance is much appreciated!

asked Dec 12, 2025 at 11:27

1 Answer 1

3

You can move the center of the arc a little bit to the right, by the corner radius that you want, so that the rounded corners "join up" with the semicircular arc.

That is, you are connecting up two little rounded 90-degree arcs with a big 180-degree arc. This picture shows the two little arcs,

enter image description here

and after having the 180-degree arc sit on top of them, it becomes

enter image description here

The little arcs (including the ones for the rounded rectangle) can be drawn by spamming addArc(tangent1End:tangent2End:radius:), using a similar technique as I described here.

The tangent end points look like this:

enter image description here

In the code I have marked the corresponding points (1-7) in comments,

func createPath(
 width: CGFloat,
 height: CGFloat,
 cutoutRadius: CGFloat,
 cornerRadius: CGFloat
) -> CGPath {
 let center = CGPoint(x: cornerRadius, y: height / 2)
 let path = CGMutablePath()
 path.move(to: .init(x: 0, y: height - cornerRadius)) // 1
 path.addArc(
 tangent1End: .init(x: 0, y: height / 2 + cutoutRadius), // 2
 tangent2End: .init(x: cutoutRadius, y: height / 2 + cutoutRadius), // 3
 radius: cornerRadius
 )
 
 path.addArc(
 center: center,
 radius: cutoutRadius,
 startAngle: .pi / 2,
 endAngle: 3 * .pi / 2,
 clockwise: true
 )
 // now path.currentPoint is at X
 
 path.addArc(
 tangent1End: .init(x: 0, y: height / 2 - cutoutRadius), // 4
 tangent2End: .zero, // 5
 radius: cornerRadius
 )
 path.addArc(
 tangent1End: .zero, // 5
 tangent2End: .init(x: width, y: 0), // 6
 radius: cornerRadius
 )
 path.addArc(
 tangent1End: .init(x: width, y: 0), // 6
 tangent2End: .init(x: width, y: height), // 7
 radius: cornerRadius
 )
 path.addArc(
 tangent1End: .init(x: width, y: height), // 7
 tangent2End: .init(x: 0, y: height), // 1
 radius: cornerRadius
 )
 path.addArc(
 tangent1End: .init(x: 0, y: height), // 1
 tangent2End: .zero,
 radius: cornerRadius
 )
 path.closeSubpath()
 return path
}
answered Dec 12, 2025 at 12:58
Sign up to request clarification or add additional context in comments.

3 Comments

Brilliant! Exactly what I needed. Many thanks!
All right, to be entirely fair, it's not precisely what I tried to describe (I wanted the cut-out arc centre to stay on the edge) but it's very close and good enough to me.
(I started another question, which builds on top of this one: stackoverflow.com/questions/79847502/…)

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.