Core Graphics Tutorial: Lines, Rectangles, and Gradients

Learn how to use Core Graphics to draw lines, rectangles, and gradients — starting by beautifying a table view! By Ron Kliffer.

Leave a rating/review
Download materials
Save for later
Share
Update note: Ron Kliffer updated this tutorial for iOS 15, Xcode 13 and Swift 5.5. Ray Wenderlich wrote the original.

Core Graphics is a cool API on iOS. As a developer, you can use it to customize your UI with some neat effects, often without involving an artist. Anything related to 2-D drawing — such as drawing shapes, filling them in and giving them gradients — is a good candidate for using Core Graphics.

With a history dating back to the early days of OS X, Core Graphics is one of the oldest APIs still used today. Perhaps this is why, for many iOS developers, Core Graphics can be somewhat intimidating at first: It’s a large API and has plenty of snags to get caught on along the way. However, since Swift 3, the C-style APIs have been updated to look and feel like the modern Swift APIs you know and love!

In this tutorial, you’ll build a Star Wars Top Trumps card app, which consists of a list of starships:

Finished starship list

… as well as a detail view for each starship.

Finished starship detail

In creating this app, you’ll learn how to get started with Core Graphics, fill and stroke rectangles and draw lines and gradients to make custom table view cells and backgrounds.

You might want to buckle up — it’s time to have some fun with Core Graphics!

Getting Started

Click the Download Materials button at the top or bottom of this tutorial to download the starter and finished projects. Open the starter project in the Sample Projects folder and look around. Specifically, check out:

  • Starship.swift: Here, you’ll find the main model for this app — Starship. It’s a simple struct with common properties of Starships. In an extension below, you’ll find the static property all that returns all the starships from the Starships.json file located in the Resources folder.
  • StarshipsViewController.swift: This is the main view controller of the app. It holds an array of all starships and displays them in a table.
  • StarshipDetailViewController.swift: This view controller displays a table of all the fields of the starship the user selected.

Build and run the app.

Note: If you don’t see a simulator available to run the project, you’re probably using an older version of Xcode. You can download Xcode 13 from Apple’s Developer portal.

Starting starship list

The landing page is the StarshipsViewController showing a list of starships from the Star Wars universe. Tap to select the Y-wing, and the app will navigate to the detail view for that ship, which shows an image of a Y-wing followed by various properties such as its cost and speed.

Starting starship detail

This is a fully functional, if pretty boring, app. It’s time to add some bling!

Analyzing the Table View Style

In this tutorial, you’ll add a different style to two table views. Look more closely at what those changes look like.

In StarshipsViewController, each cell:

  • Has a gradient from dark blue to black.
  • Is outlined in yellow, drawn inset from the cell bounds.

Starship list gradient detail

And in StarshipDetailViewController:

  • The table itself has a gradient from dark blue to black.
  • Each cell has a yellow splitter separating it from adjacent cells.

Starship detail gradient detail

To draw both of these designs, you simply need to know how to draw rectangles, gradients and lines with Core Graphics, which is what you’re about to learn. :]

Hello, Core Graphics!

Although this tutorial covers using Core Graphics on iOS, it’s important to know Core Graphics is available for all major Apple platforms, including: macOS via AppKit; iOS and tvOS via UIKit; and on the Apple Watch via WatchKit.

You can think of using Core Graphics like painting on a physical canvas: The order of drawing operations matters. For example, if you draw overlapping shapes, then the last one you add will be on top and overlap the ones below.

Apple designed Core Graphics so you, as a developer, provide instructions on what to draw separate from where to draw it.

Core Graphics Context, represented by the CGContext class, defines the where. You tell the context what drawing operations to do. There are CGContexts for drawing to bit-mapped images, drawing to PDF files and, most commonly, drawing directly into a UIView.

In this painting analogy, the Core Graphics Context represents the painter’s canvas.

Core Graphics Contexts are State Machines. When you set, say, a fill color, you set it for the entire canvas. And any shape you draw will have the same fill color until you change it.

Each UIView has its own Core Graphics Context. To draw the contents of a UIView using Core Graphics, you must write your drawing code within draw(_:) of the view. This is because iOS sets up the correct CGContext for drawing into a view immediately before calling draw(_:).

Now that you understand the basics of how to use Core Graphics within UIKit, it’s time to update your app!

Drawing Rectangles

To get started, create a view file by selecting New ▸ File… from the File menu. Select Cocoa Touch Class, click Next and then set the class name to StarshipListCellBackground. Make it a subclass of UIView, then create the class file. Add the following code to your new class:

override func draw(_ rect: CGRect) {
  // 1
  guard let context = UIGraphicsGetCurrentContext() else {
    return
  }
  // 2  
  context.setFillColor(UIColor.yellow.cgColor)
  // 3
  context.fill(bounds)
}

Breaking this down line by line:

  1. First, you get the current CGContext for this UIView instance, using UIGraphicsGetCurrentContext(). Remember, iOS set this up for you automatically before calling draw(_:). If you can’t get the context for any reason, you return early from the method.
  2. Then, you set the fill color on the context itself.
  3. Finally, you tell it to fill the bounds of the view.

As you can see, the Core Graphics API doesn’t contain a method for directly drawing a shape filled with a color. Instead, a bit like adding paint to a particular brush, you set a color as a state of CGContext and then tell the context what to paint with that color separately.

You also might have also noticed that when you called setFillColor(_:) on the context, you didn’t provide a standard UIColor. Instead, you must use a CGColor, which is the fundamental data type Core Graphics uses internally to represent colors. It’s super easy to convert a UIColor to a CGColor by just accessing the cgColor property of any UIColor.