Your First iOS & SwiftUI App: An App from Scratch

Feb 13 2023 · Swift 5.7, iOS 16, Xcode 14

Part 1: Getting Started with SwiftUI

06. SwiftUI View Modifiers

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: 05. SwiftUI Views Next episode: 07. Objects, Data & Methods

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Notes: 06. SwiftUI View Modifiers

Apple’s Human Interface Guidelines

Transcript: 06. SwiftUI View Modifiers

Alright! At this point, we’ve created the bones of our user interface.

Right now, we are using the default style for our SwiftUI views, which is quite plain. That’s a great starting point, but this doesn’t look very much like Luke’s design so far, does it?

What we want to do is to modify our SwiftUI views so that that they look more like Luke’s design. And you can do that through - you guessed it - SwiftUI View Modifiers.

SwiftUI has a bunch of built-in View Modfiers you can use in your apps to modify the style of your views. For example, there are view modifiers to add a shadow, a corner radius, or a border to your view.

Here’s an example of a view modifier that sets the opacity of a View. If opacity is 0, that means a view is fully transparent, and if it is 1, that means a view is opaque. A setting of 0.5 like you see here is partially transparent.

Text("100")
   .opacity(0.5)

Every time you apply a view modifier like this, behind the scenes SwiftUI is creating a new, modified version of the original view.

You can visualize it like this: first SwiftUI creates the original Text View, then when you apply the opacity modifier, it creates a new View that is a version of the previous view that is now partially transparent.

This is important to understand, because you can apply multiple view modifiers in a row like this:

Text("100")
  .opacity(0.5)
  .border(Color.red, width: 2)

Here we’ve added a second view modifier that adds a red border to the previous view.

Now I want you to ask yourself this question…

…what do you think the border will look like here?

Option A is that the border will be opaque, which means it’s not transparent at all.

Option B is that the border will be partially transparent.

Got your best guess? OK, let’s show the answer.

The answer is Option A: the border will be opaque.

For why this is, think back to the rule we discussed earlier: every time you apply a view modifier, behind the scenes SwiftUI is creating a new, modified version of the original view.

Let’s see how this works.

First SwiftUI creates the original Text View; second, SwiftUI returns a new view, that is the original text view but partially transparent. Third, SwiftUI takes that paritally transparent view, and now adds a red border to it. The border is not transparent, because the border modifier is just adding a red border on top of some transparent text.

So order matters! If you did want the border transparent, you should swap the order like this:

Text("100")
    .border(Color.red, width: 2)
    .opacity(0.5)

This time we’ve applied the border view modifier first, then the opacity view modifier.

The result is this time, the border is partially transparent. This is because we take some text, apply a red border to it, then make the entire set of text plus border transparent.

In this episode, we’re going to try out some view modifiers that are particularly helpful for styling Text Views: .kerning, .bold, .font, .lineSpacing, and .multilineTextAlignment.

Here we have bullseye, where we left it off in the previous episode. And we have the default styling of all of these views on our app.

I want to start styling them up starting with this first text label up here that says put the bullseye as close as you can to. And the first thing we noticed about this is that it’s bold. So let’s go back and add a bold view modifier to this text field.

And the way we do this, is to click the plus to get back to the object library, click to the tab where it says modifiers. And there’s a ton of modifiers here.

We’re modifying the text itself, so we wanna scroll down until we see the text category and we can find one for bold.

And then just drag that down to the to right after the end parentheses for text. And it’ll add a dot bold.

.bold()

And I like to put each view modifier on new lines. So press return here, to put it on a new line.

And the preview is already updated to show us the text in bold. So that’s looking good.

Looking back at Luke’s design, you can see that the text is centered. Whereas all of our text is left justified right now.

We can fix this by changing the alignment.

So I’m going to click plus again, scroll down to text to see if there’s a modifier that can help. And there’s one here that says multiline text alignment.

Again, we can drag this on right after the bold modifier. And again, I’m going to hit return right here.

.bold()
.multilineTextAlignment(.leading)

The default alignment is leading. I’m going to delete that and hit dot instead, this will show the different options we could use. We want center. So with center highlighted, you can press Return to select that option.

.multilineTextAlignment(.center)

And check it out, our text is now centered.

Alright, let’s go back to our design and you can see here there’s a little bit more spacing between the lines here, a little more than what we have right now.

So let’s see how we can do that. Open the library, scroll down to the text section again.

And let’s choose line spacing, drag that in under the text alignment.

I’ll try 10 first, which looks like a little too much compared to Luke’s design. So, let’s adjust it and try four.

.bold()
.multilineTextAlignment(.center)
.linespacing(4.0)

That seems about right. What about font size?

Looking at the Figma file, if we inspect this text, Luke actually used two different sizes here. 24 for the emoji, and then 13px for the text.

But, I’m going to break from the design and go with the 13 for all of the text, here.

So, let’s find a font modifier in the Library and add it to that Text.

.font(.title)

Dynamic Type

Now you’ll notice here that rather than setting this to a hard-coded font size, like 12, 14, et cetera it’s asked us to choose a preset font size such as title.

This leads me to a discussion of how font sizing works in iOS.

You may not know this, but iOS has system-wide setting called “dynamic type” that let’s you increase, or decrease the font size in all of the apps on your device.

However, if the app developer, in this case, YOU!, chooses a hard-coded font size for text, like say 12 points, then the app won’t respect that system-wide setting. That can be super frustrating for a user.

So instead of hard-coding a font size, Apple encourages you to use built-in text styles that they provide, like the .title text style you just saw.

To help you choose the proper built-in text style, we’ll look at Apple’s Human Interface Guidelines.

You can always get there right from Xcode’s Help menu! There’s even a keyboard shortcut.

There’s tons of great information for you in here about how to make your apps look and feel native to iOS. It’s a great resource!

But we’re looking for something specific about “Dynamic Type sizes”, which we can find under Foundations, Typography, and then on the right Specifications.

And there’s the chart for Dynamic Type sizes. You can flip between the various settings a user can pick up top.

So I’m going to pick the text style that is the closest to Luke’s design when a user is using the default Dynamic Text Size, which is Large.

According to the chart, the closest size to 13 pixels Luke wants is the footnote style, so we’ll use that.

.font(.footnote)

And now we have the proper size based on Luke’s design, and this text will resize itself based on a user’s preferences.

Preview Dynamic Type Variants

One of the nice things about SwiftUI is you can actually get a preview of what your app would look like if the user selects a different size for the dynamic type size.

You can actually preview more than one size at the same time similar to how you previewed multiple orientations. Click the “Variants” button, and then select “Dynamic Type”.

This is a great way to check that your app will still be accessible for folks with visual impairments, or people who just prefer larger or smaller text.

To get a closer look at any of the previews, again, just click on it.

Letter Spacing

OK, it’s looking pretty close to Luke’s design at this point, but there’s something that doesn’t look quite right, and it’s pretty subtle. Can you notice what it is?

If you look carefully, the spacing between the characters doesn’t match Luke’s design; Luke has them spaced out more.

If you click on this first text field you’ll see the letter spacing is set to two pixels.

Back in Xcode, open the object library again with the plus button.

There isn’t a modifer called “letter spacing”.

Traditionally, in type design, there are two terms to describe the space between characters, and SwiftUI has a modifier for both of them: kerning and tracking.

The difference is subtle and honestly, won’t matter much in most cases. It will be most noticable when there are ligatures in the text.

If you get into using different fonts, working with a lot of text, or translating to different languages, you should look more into the difference.

But in our particular use case, kerning will work just fine.

You can search for it in the library, just like this, by typing kerning into the field at the top.

And then drag it right into the code.

And I’m going to change this from 1.0 to 2.0.

.kerning(2.0)

And we see some nice spacing between our characters!