Swift
iOS
UIView
Drawing
SwiftUI

Draw line in UIView

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

To draw a line in UIView, the classic UIKit approach is to subclass the view and implement draw(_:) with Core Graphics. That works well for static or lightweight custom drawing. For reusable divider lines or animated shapes, CAShapeLayer is often a cleaner alternative.

Draw a Line with Core Graphics

When you override draw(_:), UIKit gives you a drawing context for the view. You can move to a start point, add a line to an end point, and stroke the path.

swift
1import UIKit
2
3final class LineView: UIView {
4    override func draw(_ rect: CGRect) {
5        guard let context = UIGraphicsGetCurrentContext() else { return }
6
7        context.setStrokeColor(UIColor.systemBlue.cgColor)
8        context.setLineWidth(2)
9        context.move(to: CGPoint(x: 16, y: rect.midY))
10        context.addLine(to: CGPoint(x: rect.width - 16, y: rect.midY))
11        context.strokePath()
12    }
13}

This draws a horizontal line across the middle of the view. The line is redrawn whenever the system decides the view needs display, such as after layout or explicit invalidation.

Add the Custom View Like Any Other View

Once you have the subclass, use it like a normal UIView:

swift
let lineView = LineView(frame: CGRect(x: 20, y: 100, width: 200, height: 20))
lineView.backgroundColor = .clear
view.addSubview(lineView)

Setting the background color to clear is common when the line should appear without a solid view rectangle around it.

Prefer CAShapeLayer for Many Simple Lines

If you only need a divider or a line that may animate, CAShapeLayer can be more efficient and easier to configure than overriding draw(_:).

swift
1import UIKit
2
3final class ShapeLineView: UIView {
4    private let lineLayer = CAShapeLayer()
5
6    override init(frame: CGRect) {
7        super.init(frame: frame)
8        layer.addSublayer(lineLayer)
9        lineLayer.strokeColor = UIColor.systemRed.cgColor
10        lineLayer.lineWidth = 2
11        backgroundColor = .clear
12    }
13
14    required init?(coder: NSCoder) {
15        fatalError("init(coder:) has not been implemented")
16    }
17
18    override func layoutSubviews() {
19        super.layoutSubviews()
20
21        let path = UIBezierPath()
22        path.move(to: CGPoint(x: 10, y: bounds.midY))
23        path.addLine(to: CGPoint(x: bounds.width - 10, y: bounds.midY))
24        lineLayer.path = path.cgPath
25    }
26}

This approach separates the line from the drawing cycle and is often easier to animate or restyle.

Choose the Right Tool

Use draw(_:) when:

  • You are already doing custom drawing in one place.
  • The line is part of a more complex custom graphic.
  • The view's content is naturally paint-based.

Use CAShapeLayer when:

  • You want a simple, reusable line or shape.
  • You may animate the stroke or path later.
  • You want to avoid unnecessary redraw work.

Both are valid. The right choice depends on whether the line is just one graphic element or part of a larger custom-rendered view.

Avoid Excessive Redrawing

draw(_:) is not where you should put expensive calculations. The method may be called many times across the view lifecycle. If geometry can be precomputed or represented by a layer, that is often better. Also avoid calling setNeedsDisplay() repeatedly unless the visual content truly changed.

If the line depends on Auto Layout sizing, recompute the path from bounds instead of assuming the initial frame will remain valid forever.

Common Pitfalls

  • Forgetting to call strokePath() after building the line path.
  • Doing expensive logic inside draw(_:).
  • Drawing with hardcoded coordinates that break after layout changes.
  • Using draw(_:) for a simple divider when a layer would be simpler.
  • Expecting the line to appear if the stroke color or line width was never configured.

Summary

  • Override draw(_:) and use Core Graphics for classic custom line drawing.
  • Use CAShapeLayer for lightweight reusable or animatable lines.
  • Recalculate line geometry when the view's bounds change.
  • Keep draw(_:) focused on drawing, not heavy logic.
  • Choose the simplest tool that matches how dynamic the line needs to be.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.