SwiftUI: Creating Custom Views and Manipulating Others

How to create views that keep our UI code clean and reusable while also manipulating views with other views

In part one of our series on SwiftUI, we began by making a simple profile page using SwiftUI. We got as far as:

  • Displaying our picture and name using Views
  • Setting them in a VStack
  • Apply Modifiers to have our UI follow basic design style guidelines

In this tutorial, we’ll take it a step further. We’ll learn how we can continue to modify Views, including using other Views as modification parameters. We’ll also explore how we can create our own custom Views, which will help keep our UI code clean, readable, and reusable!

Manipulating Views with Views

First, let’s mess with a Shape View; namely Circle. Let’s add a Circle() function just below our Text. In our Live Preview, you should now see our profile pushed to the top half of the screen and a giant black circle appear on the bottom half. This is part of SwiftUI’s Drawing and Animation module, along with a few other shapes (and the ability to draw our own… but that’s for another time). Let’s remove Circle before moving on.

What we can do with Circle (besides just displaying a Circle) is use it to manipulate other Views. Image, for instance, has a modifier clipShape, which will essentially crop the image inside a given shape. Try adding the following modifier to our Image: .clipShape(Circle())

Pretty neat, huh? But why stop there? What if we could put a border around the edge of our picture? Using the overlay modifier, we can create a Circle that’s an outline and place it on top of our Image. Try adding this modifier: .overlay(Circle().stroke(Color.green, lineWidth: 10))

Pretty neat, right? Go ahead and mess with this a little. Delete “green” and see what other options come up under Color. You can also change the value of lineWidth, too!

Creating Custom Views

Now let’s learn how to make our own custom views. View is actually a protocol that custom views conform to. This lets SwiftUI know that it’s a View type and can/should be displayed.

Before we create our view, let’s add a few more things to our profile. Go ahead and add two more Text views—one for a subtitle and another for a brief description. And across our three Text views, let’s set the font to .largeTitle, .title, and .body.

You’ll notice that our VStack is starting to get a little lengthy with all those Text views. This is a perfect example of an instance where we can extract and create a new view! First, wrap the three views inside a new VStack (yes, a VStack in a VStack!). Then, Cmd+Click the new VStack and choose Extract Subview.

Voila! A new custom view has been born! You’ll notice that it automatically creates the new view’s struct and calls it where the VStack was in our ContentView. It also will be prompting for a new name for our view, which I decided to call ProfileInformation.

This declutters our ContentView quite a bit, though I’d argue we could take it a step further. Why don’t we take our VStack in the ContentView and make all of our content a new View called ProfilePage?

Manually Build aCustom View

Let’s create this view manually to understand what’s going on. Let’s create our view by making a new struct for it:

By adding : View , we tell SwiftUI that this struct conforms to View. And in order to comply with that conformance, we must build-out var body since SwiftUI will look there to figure out what to build. In our body here, let’s cut and paste our VStack in ContentView. Back in our ContentView, we can simply call ProfilePage().

This may seem like overkill right now, but we’ve accomplished a few things. First, we learned how to create and extract custom views. Second, we can now call ProfilePage as many times and anywhere we like as we flesh out our app, making it much more readable and reusable.

Next, we’ll learn how we can make our views more dynamic and reactive by setting up parameters and States!

Here’s the completed code for today:

import SwiftUI

struct ContentView: View {
    var body: some View {

struct ProfileInformation: View {
    var body: some View {
            Text("Danny Bolella")
            Text("Awesome iOS Developer")
            Text("Danny loves SwiftUI and thinks it's the future of iOS Development!")

struct ProfilePage: View {
    var body: some View {
        VStack {
                .aspectRatio(contentMode: .fit)
                .overlay(Circle().stroke(Color.gray, lineWidth: 10))

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {

Tips For the Road

If there’s ever a component or View in your code you want to learn more about, simply Cmd+Click and select Show Quick Help, or Option+Click. This will bring up a brief definition from the Apple documentation. Click the link Open in Developer Documentation to open the documentation window that’ll take you straight to that definition’s page.

Editor’s Note: Heartbeat is a contributor-driven online publication and community dedicated to providing premier educational resources for data science, machine learning, and deep learning practitioners. We’re committed to supporting and inspiring developers and engineers from all walks of life.

Editorially independent, Heartbeat is sponsored and published by Comet, an MLOps platform that enables data scientists & ML teams to track, compare, explain, & optimize their experiments. We pay our contributors, and we don’t sell ads.

If you’d like to contribute, head on over to our call for contributors. You can also sign up to receive our weekly newsletters (Deep Learning Weekly and the Comet Newsletter), join us on Slack, and follow Comet on Twitter and LinkedIn for resources, events, and much more that will help you build better ML models, faster.

Avatar photo


Our team has been at the forefront of Artificial Intelligence and Machine Learning research for more than 15 years and we're using our collective intelligence to help others learn, understand and grow using these new technologies in ethical and sustainable ways.

Comments 0 Responses

Leave a Reply

Your email address will not be published. Required fields are marked *

wix banner square