How to create a Circular Progress-bar using UIKit: Swift iOS

Thulani Mtetwa
3 min readMar 14, 2023

There are multiple ways to achieve this but this way is simpler for me if you are more familiar with the UIKit framework, another good option for me is to go with the SwiftUI and UIKit interoperability route to achieve this. I recommend the latter because of Apple's direction when building UI. Enough now with the fluff let’s go…

  1. Open Xcode and click on “Create a new Xcode project” or go to “File” -> “New” -> “Project.”
  2. In the next screen, select “Application” from the left menu, and then choose “iOS” from the list of application types.
  3. Select the type of app you want to create. Xcode provides several app templates to choose from, for this tutorial we will go with “App” and click “Next.”
  4. Give your project a name and choose a location to save it on your computer.
  5. Select Swift as the language for your project.
  6. Choose any additional options, such as including unit tests or UI tests, and click “Next.”
  7. Xcode will generate the necessary files and open the project in the main window.
  8. From here, you can add new files, design the user interface, write the code for your app, and test it in the simulator or on a physical device.

Create a UIView Cocoa Touch class and call it “CircularProgressView” and add the following code.

//
// CircularProgressView.swift
// ProgressView
//
// Created by Thulani Mtetwa on 2023/03/14.
//
import Foundation
import UIKit
import QuartzCore
class CircularProgressView: UIView {

private var progressLayer = CAShapeLayer()
private var tracklayer = CAShapeLayer()

override init(frame: CGRect) {
super.init(frame: frame)
self.configureProgressViewToBeCircular()
}

required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.configureProgressViewToBeCircular()
}

var setProgressColor: UIColor = UIColor.red {
didSet {
progressLayer.strokeColor = setProgressColor.cgColor
}
}

var setTrackColor: UIColor = UIColor.white {
didSet {
tracklayer.strokeColor = setTrackColor.cgColor
}
}
/**
A path that consists of straight and curved line segments that you can render in your custom views.
Meaning our CAShapeLayer will now be drawn on the screen with the path we have specified here
*/
private var viewCGPath: CGPath? {
return UIBezierPath(arcCenter: CGPoint(x: frame.size.width / 2.0, y: frame.size.height / 2.0),
radius: (frame.size.width - 1.5)/2,
startAngle: CGFloat(-0.5 * Double.pi),
endAngle: CGFloat(1.5 * Double.pi), clockwise: true).cgPath
}

private func configureProgressViewToBeCircular() {
self.drawsView(using: tracklayer, startingPoint: 10.0, ending: 1.0)
self.drawsView(using: progressLayer, startingPoint: 10.0, ending: 0.0)
}

private func drawsView(using shape: CAShapeLayer, startingPoint: CGFloat, ending: CGFloat) {
self.backgroundColor = UIColor.clear
self.layer.cornerRadius = self.frame.size.width/2.0

shape.path = self.viewCGPath
shape.fillColor = UIColor.clear.cgColor
shape.strokeColor = setProgressColor.cgColor
shape.lineWidth = startingPoint
shape.strokeEnd = ending

self.layer.addSublayer(shape)
}

func setProgressWithAnimation(duration: TimeInterval, value: Float) {
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.duration = duration

animation.fromValue = 0 //start animation at point 0
animation.toValue = value //end animation at point specified
animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
progressLayer.strokeEnd = CGFloat(value)
progressLayer.add(animation, forKey: "animateCircle")
}
}

In the following project, I have shared how to make use of the class. click here

circular progress-bar view

Thank you. If you have any questions please post them in the comments and give me a round of applause if you found this helpful.

--

--

Thulani Mtetwa

I am an iOS App Developer. And worked on multiple apps in the finance and insurance industry.