SwiftUI Fundamentals

Feb 28 2023 · Swift 5.7, macOS Venture 13.1, Xcode 14.2

Part 1: SwiftUI Views

02. The View Protocol

Episode complete

Play next episode

Next
About this episode

Leave a rating/review

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 01. Introduction Next episode: 03. Modifiers

Notes: 02. The View Protocol

To learn more about the Swift features supporting SwiftUI, check out these chapters from our book, Swift Apprentice:

Transcript: 02. The View Protocol

The basis for everything you’ll do in SwiftUI is the View protocol. Each “view” in swiftUI will be a value type, a struct, conforming to the View protocol. View has one requirement: the Body property, which provides some sort of UI element to be rendered.

The body is where your SwiftUI code will go and whatever you write will be interpreted and rendered out to the device. Let’s start up a new SwiftUI project in Xcode to try this out ourselves.

When you open XCode and start a new project. You’ll notice the option to select ‘SwiftUI’ for the Interface! With that, you’ll get a basic project for a “Hello World” app.

It’s pretty tiny! You’ve got just two Swift files in here. The App, which loads up an instance of ContentView. And then you’ve got ContentView, which, right now, represents all of the UI in your app!

You’ve got this little bit of code on the left, a preview of the resulting UI in the canvas over here on the right. It may take a minute to load up the first time.

By default, whichever simulator or device you have selected as the current scheme is what your app will preview in, here. Any changes you make to the code…

Text("Howdy, World!")

Show up in the canvas. And if you select something in the canvas… It selects the matching code. All of this magical previewing is driven by the code at the bottom of the file. All of this is just for generating live previews onto the canvas and won’t actually run on production builds.

The naming convention of your View‘s name and an underscore isn’t necessary to get your previews working, but it is generated automatically like this. Whatever you put inside of this “previews” property will show up over in the canvas. Right now, that’s just an instance of ContentView!

Speaking of ContentView, note that its body property contains a VStack with a Image and Text component. This padding bit after it is a SwiftUI modifier. You’ll take another look at these in the next episode. Delete it for now!

}
  ❌.padding()

Remove everything but the Text view, so you can work on building it up again.

Text("Howdy, world!")

Chances are you’ll want to show something more than a lone Text view in your app. This is something that would happen fairly often in UI work, right? SwiftUI gives us access to a set of new, yet familiar primitive types such as Text, which you’ve already used, but also Image, which you got a peek at earlier.

Open the library! This is a great way to browse for new SwiftUI things to try out. In this first tab, on the left, you’ll find your options for various SwiftUI views, like Text!

Pick an image component, drag it into the code. That’s pretty cool! But the initializer you actually want to use takes the name of a system image, which will grab an SFSymbol for us! Let’s use the swift image

  Image(systemName: "swift")

If you ever need to reload the preview, you can use this button or the keyboard shortcut Option-Command-P.

Text("Hello, World!")
Image(systemName: "swift")

Over in the canvas, you should see two tabs, representing the 2 separate views in the preview struct. There are some times when this is actually the structure that you want, and you’ll take a look at that in part 2! But for now, you’re going to tell SwiftUI where you want these two things laid out in relationship to one another. The basic building block of layout in SwiftUI is the Stack.

To make one, option-command click on one of these views and embed in VStack. Then move the other view into that closure.

VStack {...}

Stacks come in 3 flavors: vertical, horizontal and depth. Just like Text and Image, all those stacks conform to View and you’ll try them all out in a later episode. Right now, check out what the VStack is doing for you over in the canvas.

My favorite thing about VStacks is their content stacks in code just like it does in the canvas. The thing on top renders on top, and then continues on down so the thing at the bottom renders at the bottom.

Ok, so, you may be wondering what is going with this some View type. You’ve effectively returned a Text, here, and now a VStack. I’ve said View is a protocol, so, you can assume that both of those other types conform to View.

But it’s a little more complicated than that, so, let’s look at its definition real quick. Command-click on View and jump to the definition. This is it!

public protocol View {
  associatedtype Body : View

  @ViewBuilder var body: Self.Body { get }
}

It’s not very long. Well, if you scroll down you’ll see it has a lot of extensions, but the base protocol itself is quite tiny. Still, there is some fancy Swift going on in those two lines of code.

You’ve got this ViewBuilder thing here. This is a property wrapper. And hey! Body is using an associated type! If you’ve dealt with protocols with associated types before you might be thinking

“hang on, now, you can’t use a protocol with an associated type here!”. And you are right! body couldn’t just be a View.

body: ❌View {...}

But it can be some View.

> Undo!

If you’re not familiar with associated types, you might be thinking “what’s the big deal”?

For now, it’s enough to know that this some keyword, and ViewBuilder, are doing some heavy lifting for you behind the scenes.

And practically, if you leave body’s type as some View, and whatever things you’ve got inside of body are some type conforming to View, the final type can be automatically inferred. You never need to set the return type manually, no matter how long or complex your view hierarchy gets.

I’ll leave some links in the authors notes in case you are interested in learning more about the Swift behind SwiftUI.

Ok! Now that you’ve got these two views here, how do we, say, change the color? Or the font size? Or anything about them at all? For that, you need to learn about modifiers!