SwiftUI Views Quick Start
SwiftUI Views Quick Start
SwiftUI Views
Quick Start
Mark Moeykens
www.bigmountainstudio.com A VISUAL REFERENCE GUIDE1 FOR SWIFTUI DEVELOPERS Big Mountain Studio
Book Version: 13-SEPTEMBER-2021
©2020 Big Mountain Studio LLC - All Rights Reserved
www.bigmountainstudio.com 2
YOU ARE READING A PREVIEW OF THE BOOK:
If you’re enjoying this book and are ready to continue your journey, then you can get the complete bundle with includes:
SwiftUI Views Mastery book (PDF & ePub)
BONUS: The FULL Xcode Project ($997 Value)
BONUS: SwiftUI Views Study Guide ($97 Value) Get the bonuses for FREE when you
FREE BONUSES
get the mastery book today.
BONUS: SwiftUI Views Flashcard Decks ($47 Value)
BONUS: My Personal Xcode Editor Theme ($17 Value)
Free Updates until next iOS version
www.bigmountainstudio.com 3
TABLE OF CONTENTS
The table of contents should be built into your ePub and PDF readers. Examples:
If you are looking for a reference guide when using SwiftUI to build your apps, then Mark has you covered with this
excellent resource here. He has been sharing his Swift knowledge for years in an easy to understand manner and
this book continues to follow this tradition.
I wish you the best in your journey to learning SwiftUI. This technology is already powerful and will only get better
with time. I have enjoyed learning SwiftUI and I think you will too.
Meng To
designcode.io
HOW TO USE
This is a visual REFERENCE GUIDE. Find a screenshot of something you
want to learn more about or produce in your app and then read it and look
at the code.
Read what is on the screenshots to learn more about the views and what
they can do.
You can also read the book from beginning to end. The choice is yours.
Conventions
CONVENTIONS
www.bigmountainstudio.com 7
Conventions
Code Formatting
Throughout this book, you may notice I don’t always follow the same formatting conventions. This is due to limited vertical space.
For example, on one page you may see code formatted like this (pseudo-code):
NewView()
.modifyTheView1()
.modifyTheView2()
And then on another page, you see code formatted like this:
NewView().modifyTheView1().modifyTheView2()
Other times, functions may be on the same line as the closing brace:
NewView {
...
}.modifyTheView2()
NewView {
...
}
.modifyTheView2()
In the end, how the code is formatted in your project is up to you. These inconsistencies are strictly due to limited page space.
www.bigmountainstudio.com 8
Conventions
Omitting Code
When using SwiftUI, the views (screens) are represented in a struct, inside a body property. (More on this later.) This will become apparent when you add your first
SwiftUI file to your project.
In most examples, you will see the struct and body property are missing. Again, this is due to limited vertical spacing. The main thing to remember is that the
relevant code is always shown.
struct MyView {
var body {
NewView()
.modifyTheView1()
.modifyTheView2()
}
}
NewView()
.modifyTheView1()
.modifyTheView2()
When space is limited, I omit the unnecessary code and show an ellipsis:
struct MyView {
var body {
... // Unnecessary code omitted
NewView()
}
}
www.bigmountainstudio.com 9
Conventions
I created a code color theme based off of another color theme called “Gruvbox”.
If you like this color theme and would like to use it in Xcode then you can find it on my GitHub as a gist here.
www.bigmountainstudio.com 10
SWIFTUI
11
Basic Concepts
Basic Concepts
If you are absolutely new to SwiftUI, you should definitely read through this chapter to establish some basic concepts that
you can think with.
www.bigmountainstudio.com 12
Basic Concepts
View
Modifiers:
• Title text size View
• Gray text color
Modifiers:
• Title text size
• Orange background color
View • Stretched to fit device width
Modifiers:
• Title text size
• White text color
• Orange background
color
• Rounded corners
• Shadow
www.bigmountainstudio.com 13
Basic Concepts
Stacks are views too. They are views that can have
modifiers applied to them.
www.bigmountainstudio.com 14
Basic Concepts
www.bigmountainstudio.com 15
Basic Concepts
www.bigmountainstudio.com 16
Basic Concepts
www.bigmountainstudio.com 17
Basic Concepts
Layout Examples
Now that you know these layout stacks, you can start to guess
how views like these might be arranged using SwiftUI.
VStack
HStack
www.bigmountainstudio.com 18
Basic Concepts
www.bigmountainstudio.com 19
Basic Concepts
www.bigmountainstudio.com 20
If you have used Swift in the past, then the SwiftUI syntax may look a little different.
It may not be readily apparent just how this code can even compile. This chapter is to help you understand how the code is
able to work.
www.bigmountainstudio.com 21
The View
struct BasicSyntax: View {
var body: some View {
Text("Hello World!") // Adds a text view to the screen
}
}
Views in SwiftUI are structs that conform to the View protocol. There is just one property to implement, the body
property.
If “body” is a property then where is the “get” and the “return” syntax?
www.bigmountainstudio.com 22
Property Getters
struct Person {
Properties can have a getter and setter. But // Computed read-only property (no set, value is not stored)
var personType: String {
when a property has no setter, it’s called a
get {
“read-only” property. And when the return "human"
}
property does not store a value, it is called a
}
“computed” property. This is because the }
value is computed or generated every time
the property is read.
In this example, personType is a computed
read-only property. // Change 1 - Remove the return
struct Person {
var personType: String {
You can further simplify this property in get {
"human"
two ways: }
}
1. When the code inside the get is a single }
expression (one thing), the getter will just
return it automatically. You can remove
return.
See “Change 1” in the code example.
// Change 2 - Remove the get
var personType: String {
2. When a property is read-only (no setter), "human"
}
we can remove the get. }
Just know that these changes are
optional.
www.bigmountainstudio.com 23
Since these property changes are optional, you can, for example, write the previous SwiftUI syntax with a get
and return inside the body property. This might look more familiar to you now:
Looking at this code again, you notice the some keyword here.
Normally, when defining a type for a property, you wouldn’t see this word.
www.bigmountainstudio.com 24
Opaque Types
struct BasicSyntax: View {
var body: some View {
Text("Hello World!")
}
}
Opaque Types
The keyword some is specifying that an opaque type is being returned. In this case, the opaque type is View.
So why is the type called “opaque”? Well, the English definition for the word “opaque”, when referring to
languages, means “hard or impossible to understand.” And this is true here because opaque types hide the
value’s type information and implementation details. This will certainly make it “hard or impossible to
understand” but still usable.
When this View (BasicSyntax) is used by iOS to draw the screen, it doesn’t have to know that, in this example,
the type Text is being returned. It is OK with just knowing that some View is being returned and can use it to
draw the screen.
And so you can return anything in that body property as long as it conforms to the View protocol.
For more information on Opaque Types, I recommend referring to the Swift Programming Language documentation.
You already know from the previous page that what is returned from the body property is something that
conforms to the View protocol.
But what you also need to know is when returning an opaque type (using the some keyword), is that all possible
return types must all be of the same type.
In most cases you are only returning one type. But you might have a scenario like this:
// ERROR: Function declares an opaque return type, but the return statements
in its body do not have matching underlying types
if isYellow {
return Color.yellow // Color type does not match the Text type
}
return Text("No color yellow") // Text type does not match the color type
}
}
The body property returns a Color and a Text type. This violates the some keyword.
www.bigmountainstudio.com 26
if isYellow {
return Color.yellow
Now, the body property always returns a Color type. This
}
satisfies the some keyword.
return Color.clear
}
}
www.bigmountainstudio.com 27
View Containers
struct Example: View {
var body: some View {
VStack {
Text("Hello World!")
Text("This Vertical Stack is using a function builder")
}
}
}
So far, you have learned that body is a computed read-only property and can only return ONE object that is some
View. What if you want to show multiple views though?
You learned earlier about the concept of “containers” views. These are views that can contain other views.
Remember, the body property can only return one view. You will get an error if you try to return more than one
view in the body property.
In the example above, the VStack (Vertical Stack) is that one view being returned. And that vertical stack is a
container with two more views inside of it.
The VStack is using a “trailing closure,” which just means that it is a code block that is passed into the initializer
to be run by the VStack. You have probably seen this before in Swift, this is not new.
What is new in Swift is the ability to create multiple, new views within the constructor like this. Before we get into
this though, let’s better understand how this constructor works.
www.bigmountainstudio.com 28
www.bigmountainstudio.com 29
My Template
If you are completely new to SwiftUI you may wonder what a lot of this code means right at the beginning of the book. I
have a certain “template” that contain a title, subtitle and a short description on most screens.
I will take you through step-by-step on how I build this template that I use throughout the book. I will describe each one
only briefly because each modifier I apply to the views are described in more detail throughout the book within their own
sections.
www.bigmountainstudio.com 31
My Template
My Basic Template
Here is my basic template I use throughout the book to explain views and modifiers.
In the next pages I’m going to explain how this is built in SwiftUI. I want to make sure you understand these
parts because you will see them everywhere in this book.
I want to remove any confusion right at the beginning so it doesn’t get in your way to learning the topics in the
book.
www.bigmountainstudio.com 32
My Template
Here, you have a Text view. You want to make it larger so you use the font modifier so you can set the size to a
SwiftUI preset size called largeTitle (this is the largest preset size).
There are more ways you can change the size of text that are covered in this book in the Control Views chapter,
in the section called Text.
www.bigmountainstudio.com 33
My Template
Add a VStack
struct AddVStack: View {
var body: some View {
// Only one view can be returned from the body property.
// Add 20 points between views within this container.
VStack(spacing: 20) { // VStack is a container view that can hold up to 10 views
Text("Title")
.font(.largeTitle)
}
}
}
VStack Spacing
The body property can only return one view.
You will get an error if you have two views. The VStack has an optional parameter you can
use in its initializer to specify how many points
So, you need to use a container view that will of spacing you want in between views. (Note:
contain multiple views. The vertical stack spacing does not add spacing to the top or
(VStack) is the perfect choice here. bottom of the VStack.)
Now you can add up to 9 more views to the Now, let’s add the subtitle text.
VStack.
www.bigmountainstudio.com 34
My Template
Text("Subtitle")
.font(.title) // Set to be the second largest font.
.foregroundColor(Color.gray) // Change text color to gray.
}
}
}
Subtitle
The subtitle is another text view. This time, you set the size to be the second largest preset size with the
title parameter.
Finally, you modify the view to change the text color to gray. (Note: instead of using Color.gray you can
also use just .gray.)
www.bigmountainstudio.com 35
My Template
Text("Subtitle")
.font(.title)
.foregroundColor(.gray)
With the description text view, you are now familiar with the font and foregroundColor modifiers. But now
you want to add a color behind the text. So you use the background modifier to set a color.
The important thing to notice here is it is not a backgroundColor modifier. That does not exist. It is a
background modifier because it adds a layer behind the view.
Color.blue is actually a view. So the background modifier is adding a blue view on a layer behind the text.
We want this view to extend to the edges of the screen. So let’s add that next.
www.bigmountainstudio.com 36
My Template
Text("Subtitle")
.font(.title)
.foregroundColor(.gray)
To extend the text to the edges of the device, we use the frame modifier. You don’t need to set a fixed value.
Instead, you can just modify the text view and say its frame’s maximum width can extend to infinity until it
hits its parent’s frame and then will stop. Its parent’s frame is the VStack.
Notice the frame modifier is now the first modifier. In SwiftUI, the order of modifiers matter.
This is looking good. It would look better though if there was more space around the text that pushed
out the blue background.
www.bigmountainstudio.com 37
My Template
Text("Subtitle")
.font(.title)
.foregroundColor(.gray)
Padding
Use the padding modifier to add space around a view. Remember, the order of modifiers matter. You
can add the padding modifier anywhere as long as it is BEFORE the background modifier. If it was
after the background, it would add space around the blue background. We want the space between the
text and the background.
www.bigmountainstudio.com 38
My Template
Version 2
When I updated the book with SwiftUI 2, I wanted a more efficient way of adding a title, subtitle and
description.
So I made my own view, called HeaderView, where I can pass in the information and it will format it.
If you're interested in how this is done, look in the Xcode project that comes with the paid book bundle
for the file “HeaderView.swift”.
www.bigmountainstudio.com 39
SwiftUI Basics
Now that you understand this basic template I use for demonstrating topics, I will start using it. Be sure to read what is on
each screenshot (or find the text in the code to read).
www.bigmountainstudio.com 40
SwiftUI Basics
Refactoring
struct Refactoring: View {
var body: some View {
VStack(spacing: 20) {
Text("Refactoring")
.font(.largeTitle) Overrides .font(.title)
Text("Reusing Modifiers")
.foregroundColor(.gray)
Text("You can put common modifiers on the parent views to be applied to all
the child views.")
.frame(maxWidth: .infinity)
.foregroundColor(Color.white)
.padding()
.background(Color.blue)
}
.font(.title) // This font style will be applied to all text views inside the
VStack.
}
}
Here, the title font is being applied to all three text views inside of the parent view (VStack).
Because the title text view sets the font again, it overrides the title size with the largeTitle size.
www.bigmountainstudio.com 41
SwiftUI Basics
Text("You will see I use icons or symbols to add clarity to what I'm
demonstrating. These come from Apple's new symbol font library which you can browse
using an app called 'SF Symbols'.")
.frame(maxWidth: .infinity)
.padding()
.background(Color.blue)
.foregroundColor(Color.white)
Even though an Image view is used to initialize a symbol, you use the font modifier to change its size. These
symbols actually come from fonts. So use font modifiers to change them. There is a whole section that covers
this.
www.bigmountainstudio.com 42
SwiftUI Basics
Layers
VStack(spacing: 40) {
Text("Layers")
.font(.largeTitle)
Text("The Basics")
.foregroundColor(.gray)
Text("With SwiftUI views, you can add layers on top (.overlay) and behind
(.background) the view.")
.frame(maxWidth: .infinity)
.padding()
.background(Color.blue)
.foregroundColor(Color.white)
Image("Layers")
}
.font(.title)
I use layers (background and overlay) early in the book so I want to make sure you understand this
concept.
www.bigmountainstudio.com 43
SwiftUI Basics
www.bigmountainstudio.com 44
Layout Behavior
In SwiftUI, you may wonder why some views layout differently than others. You can observe two behaviors when it comes
to the size and layout of views:
1. Some views pull in to be as small as possible to fit their content. (I will refer to these as “pull-in” views.)
2. Some views push out to fill all available space. (I will refer to these as “push-out” views.)
Knowing these two behaviors can help you predict what will happen when using the different views.
www.bigmountainstudio.com 45
Layout Behavior
Image(systemName: "arrow.down.to.line.alt")
Image(systemName: "arrow.up.to.line.alt")
Layout Behavior
www.bigmountainstudio.com 47
48
Preview Options
As you practice these examples, you might want to see your SwiftUI working on different devices in different modes,
including light or dark mode or with different accessibility settings.
You can do all of this without even having to launch the Simulator. When using SwiftUI, you get a preview canvas that will
show you how your views will render.
(Note: You will need to be running Xcode 11 or later on macOS Catalina or later.)
www.bigmountainstudio.com 49
Preview Options
www.bigmountainstudio.com 50
Preview Options
Introduction
struct Previews_Intro: View {
var body: some View {
VStack(spacing: 20) {
Text("Previews")
.font(.largeTitle)
Text("Introduction")
.foregroundColor(.gray)
}.font(.title)
}
}
www.bigmountainstudio.com 51
Preview Options
Dark Mode
struct Preview_DarkMode: View {
var body: some View {
VStack(spacing: 20) {
Text("Previews").font(.largeTitle)
Text("Dark Mode").foregroundColor(.gray)
Text("By default, your preview will show in light mode. To see it in dark
mode, you can use the environment modifier.")
.frame(maxWidth: .infinity)
.padding()
.background(Color.red)
.foregroundColor(.white)
}.font(.title)
}
}
www.bigmountainstudio.com 52
Preview Options
Dark Mode
www.bigmountainstudio.com 53
Preview Options
}.font(.title)
}
}
When a dark mode option is added (from the previous page) the code is updated
to use preferredColorScheme(.dark).
www.bigmountainstudio.com 54
Preview Options
www.bigmountainstudio.com 55
Preview Options
Changing Devices
struct Previews_Devices: View {
var body: some View {
VStack(spacing: 20) {
Text("Previews").font(.largeTitle)
Text("Change Devices").foregroundColor(.gray)
Text("By default, your canvas will use the simulator you
currently have selected (upper left in Xcode). You can preview a
different device using the previewDevice modifier.")
.frame(maxWidth: .infinity)
.padding()
.background(Color.red)
.foregroundColor(.white)
}.font(.title)
}
}
www.bigmountainstudio.com 56
Preview Options
Changing Devices
www.bigmountainstudio.com 57
Preview Options
Size Category
struct Preview_SizeCategory: View {
var body: some View {
VStack(spacing: 20) {
...
Text("For testing accessibility text size, set the sizeCategory property.")
...
}.font(.title)
}
}
www.bigmountainstudio.com 58
Preview Options
Size Category
www.bigmountainstudio.com 59
Preview Options
Landscape
Text("You currently cannot rotate a previewed device. But one option is to set a fixed width and height for your preview.")
I would run your project and rotate your simulator for more accurate results.
www.bigmountainstudio.com 60
Preview Options
Environment Overrides
If you prefer to see your work in the Simulator then you can access many of the
options mentioned through the Environment Overrides options.
This button will show up when you run your app in the debugging toolbar at the bottom
of Xcode.
www.bigmountainstudio.com 61
LAYOUT VIEWS
62
VStack
VStack stands for “Vertical Stack”. It is a pull-in container view in which you pass in up to ten views and it will compose them
one below the next, going down the screen.
www.bigmountainstudio.com 63
VStack
Introduction
struct VStack_Intro : View {
var body: some View {
VStack(spacing: 20) {
HeaderView("VStack",
subtitle: "Introduction",
desc: "A VStack will vertically arrange other views within it.",
back: .blue, textColor: .white)
Text("View 1")
Text("View 2")
Text("View 3")
Text("View 4")
Text("View 5")
Text("View 6")
Text("View 7")
In SwiftUI, container views, like the
Text("View 8")
VStack, can only contain up to 10
Text("View 9")
} views.
.font(.title)
}
}
www.bigmountainstudio.com 64
VStack
Nesting
struct VStack_Nesting: View {
var body: some View {
VStack(spacing: 20) {
HeaderView("VStack",
subtitle: "Nesting",
desc: "A VStack can be nested within another VStack when laying out
views.",
back: .blue, textColor: .white)
VStack {
Text("VStack inside another VStack")
Divider()
Text("This can be helpful. Why?")
Divider()
Text("More than 10 views creates an error.")
}
.padding()
.foregroundColor(Color.white)
.background(
// Use a blue rectangle as the background
RoundedRectangle(cornerRadius: 10)
.foregroundColor(.blue))
.padding()
}
.font(.title)
}
}
www.bigmountainstudio.com 65
VStack
Spacing
VStack(spacing: 80) { Set spacing in the initializer.
Text("VStack")
.font(.largeTitle)
Text("Spacing")
.font(.title)
.foregroundColor(.gray)
Text("The VStack initializer allows you to set the spacing between all the views inside the
VStack")
.frame(maxWidth: .infinity)
.padding()
.background(Color.blue).font(.title)
.foregroundColor(.white)
Image(systemName: "arrow.up.and.down.circle.fill")
.font(.largeTitle)
www.bigmountainstudio.com 66
VStack
Alignment
VStack(spacing: 20) {
Text("VStack")
.font(.largeTitle)
Text("Alignment")
.font(.title)
.foregroundColor(.gray)
Text("By default, views in a VStack are center aligned.")
...
www.bigmountainstudio.com 67
iOS 14
LazyVStack
SwiftUI 2 (iOS 14) content is locked in this preview. This is everything you get:
The complete SwiftUI Views Mastery book (PDF & ePub)
BONUS: The FULL Xcode Project ($997 Value)
BONUS: SwiftUI Views Study Guide ($97 Value)
BONUS: SwiftUI Views Flashcard Decks ($47 Value)
The Lazy Vertical Stack is similar to the VStack. It’s “lazy” because if you have views scrolling off the screen, SwiftUI will not
BONUS: My Personal Xcode Editor Theme ($17 Value)
load them unless it needs to show them on the screen. The VStack does not do this. The VStack loads all child views when
displayed. UNLOCK THE BOOK BUNDLE TODAY FOR ONLY $57!
www.bigmountainstudio.com 68
HStack
HStack stands for “Horizontal Stack”. It is a pull-in container view in which you pass in up to ten views and it will compose
them side-by-side.
www.bigmountainstudio.com 69
Introduction
struct HStack_Intro: View {
var body: some View {
VStack(spacing: 40) {
HeaderView("HStack",
subtitle: "Introduction",
desc: "An HStack will horizontally arrange other views within it.",
back: .orange)
HStack {
Text("View 1")
Text("View 2")
Text("View 3")
}
}
.font(.title)
}
}
www.bigmountainstudio.com 70
HStack
Spacing
VStack(spacing: 40) {
Text("HStack")
.font(.largeTitle)
Text("Spacing")
.font(.title)
.foregroundColor(.gray)
Text("The HStack initializer allows you to set the spacing between all the views inside the
HStack")
.frame(maxWidth: .infinity)
.padding()
.background(Color.orange).font(.title)
.foregroundColor(.black)
Text("Default Spacing")
.font(.title)
HStack {
Image(systemName: "1.circle")
Image(systemName: "2.circle")
Image(systemName: "3.circle")
}.font(.largeTitle)
Divider()
Text("Spacing: 100")
.font(.title)
HStack(spacing: 100) { Set spacing in the initializer.
Image(systemName: "1.circle")
Image(systemName: "2.circle")
Image(systemName: "3.circle")
}.font(.largeTitle)
}
www.bigmountainstudio.com 71
HStack
Alignment
Text("By default, views within an HStack are vertically aligned in the center.")
...
HStack {
Rectangle().foregroundColor(.orange).frame(width: 25)
Text("Leading")
Spacer()
Text("Center")
Spacer()
Text("Trailing")
.padding(.trailing) Set alignment in the initializer.
}
.border(Color.orange)
HStack(alignment: .top) {
Rectangle().foregroundColor(.orange).frame(width: 25)
Text("Leading")
Spacer()
Text("Top")
Spacer()
Text("Trailing")
.padding(.trailing)
}
.border(Color.orange)
HStack(alignment: .bottom) {
Rectangle().foregroundColor(.orange).frame(width: 25)
Text("Leading")
Spacer()
Text("Bottom")
Spacer()
Text("Trailing")
.padding(.trailing)
}
.border(Color.orange)
www.bigmountainstudio.com 72
HStack
Text Alignment
struct HStack_TextAlignment: View {
var body: some View {
VStack(spacing: 20) {
HeaderView("HStack",
subtitle: "Text Alignment",
desc: "HStacks have another alignment option to help better align the
bottom of text.",
back: .orange)
HStack(alignment: .bottom) {
Text("Hello")
Text("amazing")
.font(.largeTitle)
Text("developer!")
}
.font(.body)
DescView(desc: "Notice the bottom of the text isn't really aligned above. Use
firstTextBaseline or lastTextBaseline instead:", back: .orange)
HStack(alignment: .firstTextBaseline) {
Text("Hello")
Text("amazing")
.font(.largeTitle)
Text("developer!")
} This will align the text normally.
.font(.body)
But what’s the difference between first and
}
.font(.title) last text baseline? See on the next page.
}
}
www.bigmountainstudio.com 73
HStack
HStack(alignment: .firstTextBaseline) {
Text("Amazing developer")
.font(.title3)
Text("Really amazing developer")
}
.frame(width: 250)
DescView(desc: "The lastTextBaseline will align the bottom of the text on the last
lines (\"developer\" and \"developer\").", back: .orange)
HStack(alignment: .lastTextBaseline) {
Text("Amazing developer")
.font(.title3)
Text("Really amazing developer")
}
.frame(width: 250)
}
.font(.title)
}
}
www.bigmountainstudio.com 74
HStack
Customization
struct HStack_Customizing : View {
var body: some View {
VStack(spacing: 20) {
HeaderView("HStack",
subtitle: "Customizing",
desc: "HStacks are views that can have modifiers applied to them just
like any other view.",
back: .orange)
HStack {
Text("Leading")
Text("Middle")
Text("Trailing")
}
.padding()
.border(Color.orange) // Create a 2 point border using the color specified
HStack(spacing: 10) {
Image(systemName: "1.circle")
Image(systemName: "2.circle")
Image(systemName: "3.circle")
}.padding()
HStack(spacing: 20) {
Image(systemName: "a.circle.fill")
Image(systemName: "b.circle.fill")
Image(systemName: "c.circle.fill")
Image(systemName: "d.circle.fill")
Image(systemName: "e.circle.fill")
}
.font(.largeTitle).padding()
.background(RoundedRectangle(cornerRadius: 10)
.foregroundColor(.orange))
}
.font(.title)
}
}
www.bigmountainstudio.com 75
HStack
Layout Priority
When using a horizontal stack with text views within it, there’s a chance that text might truncate if
you are not allowing them to wrap. In this case, you can prioritize which one will truncate last with
layout priority. The default value is 0. The higher the number, the higher the priority to have
enough space to not be truncated.
HStack {
Text("SwiftUI")
.font(.largeTitle).lineLimit(1) // Don't let text wrap
Image("SwiftUI")
.resizable()
.frame(width: 80, height: 80)
Text("Brings Balance")
.font(.largeTitle)
.layoutPriority(1) // Truncate last
}
.padding([.horizontal])
Divider()
HStack {
Text("SwiftUI")
.font(.largeTitle)
.layoutPriority(1) // Truncate last
Image("SwiftUI")
.resizable()
.frame(width: 80, height: 80)
Text("Brings Balance")
.font(.largeTitle).lineLimit(1) // Don't let text wrap
}
.padding(.horizontal)
www.bigmountainstudio.com 76
iOS 14
LazyHStack
SwiftUI 2 (iOS 14) content is locked in this preview. This is everything you get:
The complete SwiftUI Views Mastery book (PDF & ePub)
BONUS: The FULL Xcode Project ($997 Value)
BONUS: SwiftUI Views Study Guide ($97 Value)
BONUS: SwiftUI Views Flashcard Decks ($47 Value)
The Lazy Horizontal Stack is similar to the HStack. It’s “lazy” because if you have views scrolling off the screen, SwiftUI will
BONUS: My Personal Xcode Editor Theme ($17 Value)
not load them unless it needs to show them on the screen. The HStack does not do this. The HStack loads all child views
when displayed. UNLOCK THE BOOK BUNDLE TODAY FOR ONLY $57!
www.bigmountainstudio.com 77
A Depth Stack (ZStack) is a pull-in container view. It is a view that overlays its child views on top of each other. (“Z”
represents the Z-axis which is depth-based in a 3D space.)
You learned earlier about creating layers with the background and overlay modifiers. ZStack is another way to create layers
with views that control their own sizing and spacing.
So, the ZStack is a pull-in container view but you may think it is a push-out view because of the first example but it’s actually
the color that is pushing out.
www.bigmountainstudio.com 78
ZStack
Introduction
ZStack {
// LAYER 1: Furthest back
You set depth by the order of
Color.gray // Yes, Color is a view! the views inside the ZStack.
Text("But notice the Color stops at the Safe Areas (white areas on top and bottom).")
.frame(maxWidth: .infinity)
.padding()
.background(Color.green)
}
.font(.title)
}
www.bigmountainstudio.com 79
ZStack
VStack(spacing: 20) {
Text("ZStack")
.font(.largeTitle)
Text("Ignoring the Safe Areas will extend a view to fill the whole scene.")
.frame(maxWidth: .infinity)
.padding()
.foregroundColor(.white)
.background(Color.green)
}
.font(.title)
}
.edgesIgnoringSafeArea(.all) // Ignore the safe areas
www.bigmountainstudio.com 80
ZStack
Background Problem
struct ZStack_BackgroundColor_Problem: View {
var body: some View {
ZStack {
Color.gray
VStack(spacing: 20) {
Text("ZStack") // This view is under the notch
.font(.largeTitle)
Text("Having the ZStack edges ignoring the safe areas might be a mistake if you
don't want other layers' edges to also ignore the safe areas. You notice that the top Text view
is completely under the notch.")
.frame(maxWidth: .infinity)
.padding()
.background(Color.green)
www.bigmountainstudio.com 81
ZStack
Background Solution
struct ZStack_BackgroundColor_Solution: View {
var body: some View {
ZStack {
Color.gray
.edgesIgnoringSafeArea(.all) // Have JUST the color ignore the safe areas,
not the VStack.
VStack(spacing: 20) {
Text("ZStack")
.font(.largeTitle)
Text("To solve the problem, you want just the color (bottom layer) to ignore
the safe area edges and fill the screen. Other layers above it will respect the safe areas.")
.frame(maxWidth: .infinity)
.padding()
.background(Color.green)
Spacer()
}
.font(.title)
}
}
}
www.bigmountainstudio.com 82
ZStack
Layering
struct ZStack_Layering: View {
var body: some View {
VStack(spacing: 20) {
HeaderView("ZStack",
subtitle: "Layering & Aligning",
desc: "ZStacks are great for layering views. For example, putting text on
top of an image.", back: .green, textColor: .white)
ZStack {
Image("yosemite_large")
.resizable() // Allows image to change size
.scaledToFit() // Keeps image the same aspect ratio when resizing
Rectangle()
.fill(Color.white.opacity(0.6))
.frame(maxWidth: .infinity, maxHeight: 50)
DescView(desc: "But what if you wanted to have all the views align to the bottom?",
back: .green, textColor: .white)
}
.font(.title)
}
}
www.bigmountainstudio.com 83
ZStack
Aligning
struct ZStack_Aligning: View {
var body: some View {
VStack(spacing: 20) {
HeaderView("ZStack",
subtitle: "Aligning",
desc: "The ZStack allows you to align all the views within it.",
back: .green, textColor: .white)
ZStack(alignment: .topLeading) {
Use the alignment
Image("yosemite_large") parameter in the ZStack’s
.resizable() initializer to set where you
.aspectRatio(contentMode: .fit) want all views within to be
aligned.
Rectangle()
.fill(Color.white.opacity(0.6))
.frame(maxWidth: .infinity, maxHeight: 60)
ZStack(alignment: .bottomTrailing) {
Image("yosemite_large")
.resizable()
.aspectRatio(contentMode: .fit)
www.bigmountainstudio.com 84
ZStack
Aligning
Rectangle()
.fill(Color.white.opacity(0.6))
.frame(maxWidth: .infinity, maxHeight: 60)
Alignment Choices
Text("Yosemite National Park")
.font(.title) • center
.padding()
} • leading
}
.font(.title) • trailing
}
} • top
• bottom
• topLeading
• topTrailing
• bottomLeading
• bottomTrailing
www.bigmountainstudio.com 85
Spacer
You may notice that when you add new pull-in views, such as Text views, they appear in the center of the screen. You can
use the Spacer to push these views apart, away from the center of the screen.
www.bigmountainstudio.com 86
Spacer
Introduction
VStack {
Text("Spacer")
.font(.largeTitle)
Text("Introduction")
.foregroundColor(.gray)
Image(systemName: "arrow.up.circle.fill")
Image(systemName: "arrow.down.circle.fill")
HStack {
Text("Horizontal Spacer")
Image(systemName: "arrow.left.circle.fill")
Image(systemName: "arrow.right.circle.fill")
}
.padding(.horizontal)
Color.yellow
.frame(maxHeight: 50) // Height can decrease but not go higher than 50
}
.font(.title) // Apply this font to every view within the VStack
www.bigmountainstudio.com 87
Spacer
Evenly Spaced
Text("Use Spacer to evenly space views horizontally so they look good on any
device.")
...
Text("After")
...
HStack {
Spacer()
VStack(alignment: .leading) {
Text("Names")
.font(.largeTitle)
.underline()
Text("Chase")
Text("Rodrigo")
Text("Mark")
Text("Evans")
}
Spacer()
VStack(alignment: .leading) {
Text("Color")
.font(.largeTitle)
.underline()
Text("Red")
Text("Orange")
Text("Green")
Text("Blue")
}
Spacer()
}
www.bigmountainstudio.com 88
Spacer
Minimum Length
VStack(spacing: 10) {
Text("Spacer")
.font(.largeTitle)
Text("Minimum Length")
.font(.title)
.foregroundColor(.gray)
Text("You can set a minimum space to exist between views using the minLength modifier on the
Spacer.")
...
Text("No minLength set (system default is used)")
.bold()
HStack {
Image("yosemite")
Spacer()
Text("This is Yosemite National Park").lineLimit(1)
}.padding()
Text("minLength = 0")
Set the minimum length in the
.bold()
HStack { Spacer’s initializer.
Image("yosemite")
Spacer(minLength: 0)
Text("This is Yosemite National Park").lineLimit(1)
}.padding()
Text("minLength = 20")
.bold()
HStack {
Image("yosemite")
Spacer(minLength: 20)
Text("This is Yosemite National Park").lineLimit(1)
}.padding()
}
www.bigmountainstudio.com 89
Spacer
www.bigmountainstudio.com 90
Spacer
Spacer()
.frame(width: 5)
.background(Color.blue)
Text("75% Down")
Spacer()
.frame(width: 5)
.background(Color.blue)
}
}
}.font(.title)
}
}
www.bigmountainstudio.com 91
GeometryReader
It is difficult, if not impossible, to get the size of a view. This is where the GeometryReader comes in.
The GeometryReader is similar to a push-out container view in that you can add child views to it. It will allow you to inspect
and use properties that can help with positioning other views within it. You can access properties like height, width and safe
area insets which can help you dynamically set the sizes of views within it so they look good on any size device.
www.bigmountainstudio.com 92
Geometry Reader
Introduction
struct GeometryReader_Intro : View {
var body: some View {
VStack(spacing: 20) {
HeaderView("GeometryReader", subtitle: "Introduction", desc: "GeometryReader is a
container view that pushes out to fill up all available space. You use it to help with
positioning items within it.",
back: .clear)
GeometryReader {_ in
In SwiftUI, when you see the word
// No child views inside
“geometry”, think size and position.
}
.background(Color.pink)
}
.font(.title)
}
}
www.bigmountainstudio.com 93
Geometry Reader
Alignment
struct GeometryReader_Alignment: View {
var body: some View {
VStack(spacing: 20) {
HeaderView("GeometryReader", subtitle: "Alignment", desc: "Child views within the
GeometryReader are aligned in the upper left corner by default.", back: .clear)
GeometryReader {_ in
Image(systemName: "arrow.up.left")
Notice that there is no alignment or
.padding()
positioning specified on the image.
}
.background(Color.pink)
}
.font(.title)
}
}
www.bigmountainstudio.com 94
Geometry Reader
Layers
struct GeometryReader_Layers: View {
var body: some View {
VStack(spacing: 20) {
HeaderView("GeometryReader", subtitle: "Layers", desc: "The child views within a
GeometryReader will stack on top of each other, much like a ZStack.",
back: .clear)
GeometryReader {_ in
Image(systemName: "18.circle") Note, I wouldn’t recommend using a
.padding() GeometryReader in place of a
Image(systemName: "20.square") ZStack.
.padding()
Image(systemName: "50.circle")
ZStack provides convenient
.padding()
}
alignment options for layout that
.font(.largeTitle) GeometryReader does not.
.foregroundColor(.white)
.background(Color.pink)
}
.font(.title)
}
}
www.bigmountainstudio.com 95
Geometry Reader
Getting Size
struct GeometryReader_GettingSize : View {
var body: some View {
VStack(spacing: 10) {
HeaderView("GeometryReader", subtitle: "Getting Size", desc: "Use the geometry
reader when you need to get the height and/or width of a space.",
back: .clear)
Define a parameter to
reference the geometry’s
GeometryReader { geometryProxy in coordinate space from a
VStack(spacing: 10) { “proxy”.
Text("Width: \(geometryProxy.size.width)")
Text("Height: \(geometryProxy.size.height)")
The GeometryProxy is a
}
.padding()
representation of the
.foregroundColor(.white) GeometryReader’s size and
This is the actual width and } coordinate space.
.background(Color.pink)
height of the GeometryReader
}
view (pink area).
.font(.title)
}
The geometryProxy.size will
}
give you access to the height
and width of the space the
GeometryReader is taking up
on the screen.
www.bigmountainstudio.com 96
Geometry Reader
Positioning
struct GeometryReader_Positioning: View {
var body: some View {
VStack(spacing: 20) {
Text("GeometryReader").font(.largeTitle)
Text("Positioning").font(.title).foregroundColor(.gray)
Text("Use the GeometryProxy input parameter to help position child views at
different locations within the geometry's view.")
.font(.title)
.padding()
GeometryReader { geometryProxy in
Text("Upper Left")
.font(.title)
.position(x: geometryProxy.size.width/5,
y: geometryProxy.size.height/10)
Text("Lower Right")
.font(.title)
.position(x: geometryProxy.size.width - 90,
y: geometryProxy.size.height - 40)
}
.background(Color.pink)
.foregroundColor(.white)
Text("Note: The position modifier uses the view's center point when setting the X
and Y parameters.")
.font(.title)
}
}
}
www.bigmountainstudio.com 97
Geometry Reader
Getting Coordinates
struct GeometryReader_GettingCoordinates : View {
var body: some View {
VStack(spacing: 10) {
HeaderView("GeometryReader", subtitle: "Getting Coordinates", desc: "Getting the
coordinates (x, y) of a geometry view is little different. Take a look at this example:",
back: .clear)
GeometryReader { geometryProxy in
VStack(spacing: 10) {
Text("X: \(geometryProxy.frame(in: CoordinateSpace.local).origin.x)")
Text("Y: \(geometryProxy.frame(in: CoordinateSpace.local).origin.y)")
}
.foregroundColor(.white)
}
.background(Color.pink)
www.bigmountainstudio.com 98
Geometry Reader
GeometryReader { geometry in
VStack(alignment: .leading, spacing: 20) {
Text("Local Coordinate Space")
HStack(spacing: 10) {
// I'm converting to Int just so we don't have so many zeros
Text("minX: \(Int(geometry.frame(in: .local).minX))")
Spacer()
Text("midX: \(Int(geometry.frame(in: .local).midX))")
Spacer()
Text("maxX: \(Int(geometry.frame(in: .local).maxX))")
}
Text("Global Coordinate Space")
HStack(spacing: 10) {
// I'm converting to Int just so we don't have so many zeros
Text("minX: \(Int(geometry.frame(in: .global).minX))")
Spacer()
Text("midX: \(Int(geometry.frame(in: .global).midX))")
Spacer()
Text("maxX: \(Int(geometry.frame(in: .global).maxX))")
}
}.padding(.horizontal)
}
www.bigmountainstudio.com 99
Geometry Reader
HStack {
GeometryReader { geometry in
VStack(spacing: 10) {
Text("minY: \(Int(geometry.frame(in: .global).minY))")
Spacer()
Text("midY: \(Int(geometry.frame(in: .global).midY))")
Spacer()
Text("maxY: \(Int(geometry.frame(in: .global).maxY))")
}.padding(.vertical)
}
.foregroundColor(.white)
.background(Color.pink)
Image("MinMidMax")
.resizable()
.aspectRatio(contentMode: .fit)
}
}
.font(.title)
.padding()
}
} Notice how the min, mid and max values change as the
geometry reader adapts to different device sizes.
www.bigmountainstudio.com 100
Geometry Reader
HeaderView("GeometryReader", subtitle: "SafeAreaInsets", desc: "GeometryReader can also tell you the safe area insets it has.",
back: .clear)
GeometryReader { geometryProxy in
VStack {
Text("geometryProxy.safeAreaInsets.leading: \(geometryProxy.safeAreaInsets.leading)")
Text("geometryProxy.safeAreaInsets.trailing: \(geometryProxy.safeAreaInsets.trailing)")
Text("geometryProxy.safeAreaInsets.top: \(geometryProxy.safeAreaInsets.top)")
Text("geometryProxy.safeAreaInsets.bottom: \(geometryProxy.safeAreaInsets.bottom)")
}
.padding()
}
.background(Color.pink)
.foregroundColor(.white)
www.bigmountainstudio.com 101
iOS 14
LazyHGrid
SwiftUI 2 (iOS 14) content is locked in this preview. This is everything you get:
The complete SwiftUI Views Mastery book (PDF & ePub)
BONUS: The FULL Xcode Project ($997 Value)
BONUS: SwiftUI Views Study Guide ($97 Value)
BONUS: SwiftUI Views Flashcard Decks ($47 Value)
Similar to an HStack, the Lazy Horizontal Grid will layout views horizontally but can be configured to use multiple rows and
BONUS: My Personal Xcode Editor Theme ($17 Value)
scroll off the screen. The word “lazy” here means that the child views are only created when SwiftUI needs them. This is
called “lazy loading”. UNLOCK THE BOOK BUNDLE TODAY FOR ONLY $55!
www.bigmountainstudio.com 102
iOS 14
LazyVGrid
SwiftUI 2 (iOS 14) content is locked in this preview. This is everything you get:
The complete SwiftUI Views Mastery book (PDF & ePub)
BONUS: The FULL Xcode Project ($997 Value)
BONUS: SwiftUI Views Study Guide ($97 Value)
BONUS: SwiftUI Views Flashcard Decks ($47 Value)
Similar to an HStack, the Lazy Vertical GridBONUS:
will layout views vertically but can be configured to use multiple columns and
My Personal Xcode Editor Theme ($17 Value)
scroll off the screen. The word “lazy” here means that the child views are only created when SwiftUI needs them. This is
called “lazy loading”. UNLOCK THE BOOK BUNDLE TODAY FOR ONLY $55!
103
ScrollViewReader
iOS 14
ScrollViewReader
SwiftUI 2 (iOS 14) content is locked in this preview. This is everything you get:
The complete SwiftUI Views Mastery book (PDF & ePub)
BONUS: The FULL Xcode Project ($997 Value)
BONUS: SwiftUI Views Study Guide ($97 Value)
BONUS: SwiftUI Views Flashcard Decks ($47 Value)
BONUS: My Personal Xcode Editor Theme ($17 Value)
The Scroll View Reader gives you access to a function called scrollTo. With this function you can make a view within a scroll
UNLOCK
view visible by automatically scrolling to it. THE BOOK BUNDLE TODAY FOR ONLY $55!
www.bigmountainstudio.com 104
CONTROL VIEWS
105
Button
The Button is a pull-in view with a wide range of composition and customization options to be presented to the user. The
button can be just text, just an image or both combined.
www.bigmountainstudio.com 106
Button
Introduction
VStack(spacing: 20) {
Text("Button")
.font(.largeTitle)
Text("Introduction")
.font(.title).foregroundColor(.gray)
Text("If you just want to show the default text style in a button then you can pass in a
string as the first parameter")
...
www.bigmountainstudio.com 107
Button
Text Composition
struct Button_TextModifiers : View {
var body: some View {
VStack(spacing: 20) {
Text("Button").font(.largeTitle)
Text("Text Composition").foregroundColor(.gray)
Text("You can add more than one text view to a button. By default, the views are
composed within an HStack.")
.padding().frame(maxWidth: .infinity)
.background(Color.purple)
.foregroundColor(.white).font(.title)
Text("Using a VStack")
.padding().frame(maxWidth: .infinity)
.background(Color.purple)
.foregroundColor(.white)
www.bigmountainstudio.com 108
Button
With Backgrounds
Text("Button").font(.largeTitle)
Text("With Backgrounds").font(.title).foregroundColor(.gray)
Text("As with most views, we can also customize the background and add a shadow.")
.padding().frame(maxWidth: .infinity)
.background(Color.purple)
.foregroundColor(.white).font(.title)
You will learn another way to
Button(action: {}) {
do this using Shapes in the
Text("Solid Button")
.padding() “Other Views” chapter.
.foregroundColor(Color.white)
.background(Color.purple)
.cornerRadius(8)
}
Button(action: {}) {
Text("Button With Shadow")
.padding(12)
.foregroundColor(Color.white)
.background(Color.purple)
.cornerRadius(8)
}
.shadow(color: Color.purple, radius: 20, y: 5) // See more info in the section on Shadows
Button(action: {}) {
Text("Button With Rounded Ends")
.padding(EdgeInsets(top: 12, leading: 20, bottom: 12, trailing: 20))
.foregroundColor(Color.white)
.background(Color.purple)
.cornerRadius(.infinity) // Infinity will always give you the perfect corner no matter
the size of the view.
}
www.bigmountainstudio.com 109
Button
With Borders
Text("Button").font(.largeTitle)
Text("With Borders").font(.title).foregroundColor(.gray)
Text("Applying borders can add a nice effect to your buttons. Here are some options.")
.padding().frame(maxWidth: .infinity)
.background(Color.purple)
.foregroundColor(.white).font(.title)
Button(action: {}) {
Text("Square Border Button")
.padding()
.border(Color.purple)
}
Button(action: {}) {
Text("Rounded Border Button")
.padding()
.border(Color.purple)
.cornerRadius(10)
}
Text("Look what happened when I tried to add a corner radius to the border. It is clipping the
corners. Here is a different way you can accomplish this:")
...
Button(action: {}) {
Text("Border Button")
.padding()
.background(
RoundedRectangle(cornerRadius: 10)
.stroke(Color.purple, lineWidth: 2)
)
}
www.bigmountainstudio.com 110
Button
With SF Symbols
Button(action: {}) {
Text("Button With Symbol")
.padding(.horizontal)
Image(systemName: "gift.fill")
}
.padding()
.foregroundColor(Color.white)
.background(Color.purple)
.cornerRadius(8)
Button(action: {}) {
Image(systemName: "magnifyingglass")
Text("Search")
.padding(.horizontal)
}
.padding()
.foregroundColor(Color.white)
.background(Color.purple)
.cornerRadius(8)
Button(action: {}) {
VStack {
Image(systemName: "video.fill")
Text("Record")
.padding(.horizontal)
} For even more ways to customize buttons,
}
see the chapter on Paints where you can
.padding()
.foregroundColor(Color.white) learn how to apply the 3 different gradients
.background(Color.purple) to them.
.cornerRadius(.infinity)
www.bigmountainstudio.com 111
Button
With Images
struct Button_WithPhotos: View {
var body: some View {
VStack(spacing: 20) {
Text("Button").font(.largeTitle)
Text("With Images")
.font(.title).foregroundColor(.gray)
Text("Buttons work fine with the SF Symbols. But what if you wanted to use a photo?
Look what happens:")
...
Button(action: {}) {
Image("yosemite")
.cornerRadius(40)
}
Button(action: {}) {
Image("yosemite")
// Change rendering mode to original
.renderingMode(.original)
.cornerRadius(40)
}
}
}
}
www.bigmountainstudio.com 112
Button
Text("Floating")
.font(.title).foregroundColor(.gray)
Text("You can also create floating buttons by using a ZStack so the button is on the top
layer, over everything else")
...
Spacer()
}
VStack {
Spacer()
HStack {
Spacer()
Button(action: {}) {
Image(systemName: "plus")
.font(.title)
}
.padding(20)
.foregroundColor(Color.white)
.background(Color.purple)
.cornerRadius(.infinity)
}
.padding(.trailing, 30) // Add 30 points on the trailing side of the button
}
}
www.bigmountainstudio.com 113
ColorPicker
iOS 14
ColorPicker
!
SwiftUI 2 (iOS 14) content is locked in this preview. This is everything you get:
The complete SwiftUI Views Mastery book (PDF & ePub)
BONUS: The FULL Xcode Project ($997 Value)
BONUS: SwiftUI Views Study Guide ($97 Value)
The ColorPicker control allows you to give users the ability to select a color. This could be useful if you want to allow users
BONUS: SwiftUI Views Flashcard Decks ($47 Value)
to set the color of visual elements on the user interface.
BONUS: My Personal Xcode Editor Theme ($17 Value)
This is a push-out horizontal view.UNLOCK THE BOOK BUNDLE TODAY FOR ONLY $55!
www.bigmountainstudio.com 114
DatePicker in iOS 13
In order to get or set a value for the DatePicker, you need to bind it to a variable. This variable is then passed into the
DatePicker’s initializer. Then, all you need to do is change the value of the bound variable to set the date or time you want
to show in the DatePicker. Or read the bound variable’s value to see which date or time is currently selected.
Note: This is how the DatePicker looks in iOS 13. The iOS 14 DatePicker looks completely different and is at the end
of this section.
www.bigmountainstudio.com 115
DatePicker
Introduction
struct DatePicker_Intro : View {
// The date picker will use this variable to get and set its value
@State private var nextFullMoonDate = Date()
HStack {
Spacer()
Image(systemName: "moon.circle")
Spacer()
Circle().frame(width: 60, height: 60.0)
Spacer()
Image(systemName: "moon.circle.fill")
Spacer()
}
.foregroundColor(Color.yellow)
www.bigmountainstudio.com 116
DatePicker
Titles
struct DatePicker_Titles: View {
@State private var nextFullMoonDate = Date()
Text("This doesn't really look good. So you might want to add your own title.")
.padding().frame(maxWidth: .infinity)
.background(Color.yellow)
.font(.title)
}
}
}
www.bigmountainstudio.com 117
DatePicker
VStack(spacing: 0) {
Text("Date of next full moon")
.font(.title)
DatePicker("", selection: $nextFullMoonDate,
displayedComponents: .date)
}
www.bigmountainstudio.com 118
DatePicker
Labels Hidden
struct DatePicker_LabelsHidden: View {
@State private var nextFullMoonDate = Date()
Text("Labels Hidden")
.foregroundColor(.gray)
Text("You use the .labelsHidden modifier to let SwiftUI know not to render or
reserve space for the label (title).")
.padding()
.frame(maxWidth: .infinity)
.background(Color.yellow)
VStack(spacing: 0) {
Text("Date of next full moon")
DatePicker("Select a date for next full moon",
selection: $nextFullMoonDate,
displayedComponents: .date)
.labelsHidden() // Hide the label/title
}
}
.font(.title)
You will see later how labelsHidden can apply to many views with labels,
} not just the DatePicker.
}
Note: Even though the label/title is not shown, I would still recommend having one because it will still
be used for accessibility purposes.
www.bigmountainstudio.com 119
DatePicker
Displayed Components
struct DatePicker_DisplayedComponents: View {
@State private var justTime = Date()
@State private var theDateAndTime = Date()
www.bigmountainstudio.com 120
DatePicker
Text("The date picker looks different when used in a form. The first parameter
called 'title' is used when in forms and lists.")
.frame(maxWidth: .infinity)
.padding()
.listRowBackground(Color.yellow)
.font(.title)
www.bigmountainstudio.com 121
DatePicker
www.bigmountainstudio.com 122
DatePicker
Image("baby")
.resizable()
.aspectRatio(contentMode: .fit)
www.bigmountainstudio.com 123
DatePicker
www.bigmountainstudio.com 124
iOS 14
DatePicker in iOS 14
SwiftUI 2 (iOS 14) content is locked in this preview. This is everything you get:
The complete SwiftUI Views Mastery book (PDF & ePub)
BONUS: The FULL Xcode Project ($997 Value)
BONUS: SwiftUI Views Study Guide ($97 Value)
The date picker for iOS 14 functions just like the previous date picker. I added this new section to give you an idea of the
BONUS: SwiftUI Views Flashcard Decks ($47 Value)
visual changes as well as some new options.
BONUS: My Personal Xcode Editor Theme ($17 Value)
This is a push-out view. UNLOCK THE BOOK BUNDLE TODAY FOR ONLY $55!
www.bigmountainstudio.com 125
Form
The Form view is a great choice when you want to show settings, options, or get some user input. It is easy to set up and
customize as you will see on the following pages.
www.bigmountainstudio.com 126
Form
Introduction
struct Form_Intro : View {
var body: some View {
Form {
Section {
Text("This is a Form!")
.font(.title)
Text("You can put any content in here")
Text("The cells will grow to fit the content")
Text("Remember, it's just views inside of views")
}
Section {
Text("Limitations")
.font(.title)
Text("There are built-in margins that are difficult to get around. Take a look
at the color below so you can see where the margins are:")
Color.purple
}
Section {
Text("Summary")
.font(.title)
Text("Pretty much what you see here is what you get.")
}
}
}
}
www.bigmountainstudio.com 127
Form
www.bigmountainstudio.com 128
Form
Text("Forms and Lists allow you to set a background view with a function called
\"listRowBackground(view:)\".")
.fixedSize(horizontal: false, vertical: true)
// Using fixedSize is another way to get text not to truncate.
// See chapter on "Layout Modifiers" in full book.
Text("You can call this modifier function on just one row, like this.")
.listRowBackground(Color.purple)
.foregroundColor(.white)
}
Image(systemName: "smiley.fill")
.frame(maxWidth: .infinity, alignment: .center)
.font(.largeTitle)
Text("Note, even though the color is set on the Section, the color of the
section header is not affected.")
.fixedSize(horizontal: false, vertical: true)
}
.foregroundColor(.white)
.listRowBackground(Color.purple)
}.font(.title)
}
}
www.bigmountainstudio.com 129
Form
Background Images
Form {
Section(header: Text("Form")
.font(.largeTitle).bold()
.foregroundColor(.white)) {
Text("List Row Background")
.font(.title)
.foregroundColor(.gray)
Text("Images work a little differently as you can see here.")
Text("The image is actually set on a row on the second section.")
}
Section(header: Text("Images")
.font(.title)
.foregroundColor(.white)) {
Text("An image is set as a background for the row below. This works fine for rows,
but when you use an image on the section level, it is repeated for all rows.")
Text("The image is set on THIS row, but it extends past the bounds. It also hides
the row below this one and goes under the previous rows.")
.foregroundColor(.white)
.foregroundColor(.white)
.listRowBackground(Image("water")
.clipped()
.blur(radius: 3))
Text("This row cannot be seen.")
}
}
www.bigmountainstudio.com 130
Form
www.bigmountainstudio.com 131
Form
With Controls
struct Form_WithControls : View {
@State private var isOn = true
@State private var textFieldData = "This is a text field"
Section {
Button(action: {}) { Text("Button") }
Toggle(isOn: $isOn) { Text("Toggle") }
Stepper(onIncrement: {}, onDecrement: {}) { Text("Stepper") }
TextField("", text: $textFieldData)
.textFieldStyle(RoundedBorderTextFieldStyle())
Image(systemName: "leaf.arrow.circlepath").font(.title)
Circle()
Text("Notice shapes are centered ☝ ")
TextField("", text: $textFieldData)
.textFieldStyle(RoundedBorderTextFieldStyle())
}
}
}
}
www.bigmountainstudio.com 132
GroupBox
iOS 14
GroupBox
Box
SwiftUI 2 (iOS 14) content is locked in this preview. This is everything you get:
The complete SwiftUI Views Mastery book (PDF & ePub)
BONUS: The FULL Xcode Project ($997 Value)
BONUS: SwiftUI Views Study Guide ($97 Value)
BONUS: SwiftUI Views Flashcard Decks ($47 Value)
The group box is container for grouping similar items together.
BONUS: My Personal Xcode Editor Theme ($17 Value)
The GroupBox is a pull-in view. UNLOCK THE BOOK BUNDLE TODAY FOR ONLY $55!
www.bigmountainstudio.com 133
iOS 14
Label
Label
SwiftUI 2 (iOS 14) content is locked in this preview. This is everything you get:
The complete SwiftUI Views Mastery book (PDF & ePub)
BONUS: The FULL Xcode Project ($997 Value)
BONUS: SwiftUI Views Study Guide ($97 Value)
The label view is a pretty simple view that will handle the layout, spacing and formatting of an image and text that you pass
BONUS: SwiftUI Views Flashcard Decks ($47 Value)
into it. BONUS: My Personal Xcode Editor Theme ($17 Value)
This is a pull-in view. UNLOCK THE BOOK BUNDLE TODAY FOR ONLY $55!
www.bigmountainstudio.com 134
Link
iOS 14
Link
SwiftUI 2 (iOS 14) content is locked in this preview. This is everything you get:
The complete SwiftUI Views Mastery book (PDF & ePub)
BONUS: The FULL Xcode Project ($997 Value)
BONUS: SwiftUI Views Study Guide ($97 Value)
BONUS: SwiftUI Views Flashcard Decks ($47 Value)
The Link is similar to the Button or the NavigationLink except it can navigate you to a place outside your app.
BONUS: My Personal Xcode Editor Theme ($17 Value)
This is a pull-in view. UNLOCK THE BOOK BUNDLE TODAY FOR ONLY $55!
www.bigmountainstudio.com 135
List
Using a List view is the most efficient way of displaying vertically scrolling data. You can display data in a ScrollView, as you
will see later on, but it will not be as efficient in terms of memory or performance as the List view.
www.bigmountainstudio.com 136
List
List {
Text("Line One")
Text("Line Two")
Text("Line Three")
Image("profile")
Button("Click Here", action: {})
.foregroundColor(.green)
HStack {
Spacer()
Text("Centered Text")
Spacer()
}.padding()
}
.font(.title)
}
}
}
www.bigmountainstudio.com 137
List
With Data
struct List_WithData : View {
var stringArray = ["This is the simplest List", "Evans", "Lemuel James Guerrero", "Mark",
"Durtschi", "Chase", "Adam", "Rodrigo", "Notice the automatic wrapping when the content is
larger"]
In this scenario, we are using “self” to say, “Just use the value of the string itself to uniquely identify each
row.”
www.bigmountainstudio.com 138
List
Spacer()
Notice that with the grouped list style that the rows don’t continue past the last one.
One more thing to note is that inside the List you see an HStack used for the row. This is optional. By
default, the list will implicitly use an HStack for the row if one is not specified.
www.bigmountainstudio.com 139
List
Custom Rows
struct List_CustomRows : View {
var data = ["Custom Rows!", "Evans", "Lemuel James Guerrero", "Mark", "Durtschi", "Chase",
"Adam", "Rodrigo"]
www.bigmountainstudio.com 140
List
Delete Rows
struct List_Delete : View {
@State var data = ["Swipe to Delete", "Practice Coding", "Grocery shopping", "Get tickets",
"Clean house", "Do laundry", "Cook dinner", "Paint room"]
These three functions only work on views that implement the DynamicViewContent protocol. Currently,
the only view that conforms to the DynamicViewContent protocol is the ForEach view. So these
functions are only available on a ForEach view, not a List view.
www.bigmountainstudio.com 141
List
Move Rows
struct List_MoveRow : View {
@State var data = ["Hit the Edit button to reorder", "Practice Coding", "Grocery shopping",
"Get tickets", "Clean house", "Do laundry", "Cook dinner", "Paint room"]
What is EditButton()?
This is a built-in function that returns a view (Button) that will automatically toggle edit mode on the List.
Its text says “Edit” and then when tapped you will see the move handles appear on the rows and the
button text says “Done”.
www.bigmountainstudio.com 142
List
www.bigmountainstudio.com 143
List
// This logic was inline but the compiler said it was "too complex" 🤷
func getTextColor(due: String) -> Color {
due == "Today" ? Color.black : Color.primary
}
}
www.bigmountainstudio.com 144
List
www.bigmountainstudio.com 145
List
www.bigmountainstudio.com 146
List
www.bigmountainstudio.com 147
iOS 14
Menu
This is a pull-in view. UNLOCK THE BOOK BUNDLE TODAY FOR ONLY $55!
www.bigmountainstudio.com 148
NavigationView
The NavigationView is a little different in that it will fill the whole screen when used. You will never have to specify its size.
But there are some ways you can customize it which you will see in the following pages.
www.bigmountainstudio.com 149
NavigationView
Introduction
struct Navigation_Intro : View {
var body: some View {
NavigationView {
ZStack {
Color("Theme3BackgroundColor")
VStack(spacing: 25) {
Image(systemName: "globe")
.font(.largeTitle)
HeaderView("NavigationView",
subtitle: "Introduction",
desc: "Having a NavigationView will show nothing unless you also
include a navigationTitle modifier.",
back: Color("Theme3ForegroundColor"),
textColor: Color("Theme3BackgroundColor"))
Spacer()
}
.font(.title)
.padding(.top, 25) The navigationTitle goes INSIDE the
}
NavigationView, not on it.
// This creates a title in your nav bar
.navigationTitle("Navigation Views")
.ignoresSafeArea(edges: .bottom) Also notice that the default style of
}
the nav bar is large. How can you
}
}
change this?
www.bigmountainstudio.com 150
NavigationView
Background Color
struct Navigation_BackgroundColor: View {
var body: some View {
NavigationView {
ZStack {
Color("Theme3BackgroundColor")
.ignoresSafeArea() // Allows background color to go BEHIND large nav bar.
VStack(spacing: 25) {
Image(systemName: "globe")
.font(.largeTitle)
HeaderView("NavigationView", subtitle: "Background Color", desc: "With the
larger navigation bar, you can have a background color extend underneath it.",
back: Color("Theme3ForegroundColor"),
textColor: Color("Theme3BackgroundColor"))
Spacer()
}
.font(.title)
.padding(.top, 25)
}
.navigationTitle("Navigation Views")
}
}
}
www.bigmountainstudio.com 151
NavigationView
Display Mode
struct Navigation_DisplayMode: View {
var body: some View {
NavigationView {
ZStack {
Color("Theme3BackgroundColor")
VStack(spacing: 25) {
Image(systemName: "globe")
.font(.largeTitle)
HeaderView("NavigationView",
subtitle: "Display Mode",
desc: "For the navigation bar display mode, you can specify if
you want it large or small (inline) or just automatic.",
back: Color("Theme3ForegroundColor"),
textColor: Color("Theme3BackgroundColor"))
Spacer()
}
.font(.title)
.padding(.top, 25)
}
.navigationTitle("Navigation Views")
// Use .inline for the smaller nav bar Using .inline will render the
.navigationBarTitleDisplayMode(.inline)
smaller nav bar.
.ignoresSafeArea(edges: .bottom)
}
}
}
www.bigmountainstudio.com 152
NavigationView
NavigationBarHidden
struct Navigation_BarHidden: View {
@State private var isHidden = true
HeaderView("NavigationView",
subtitle: "Navigation Bar Hidden",
desc: "If you don't want to show a navigation bar, you can use
the navigationBarHidden modifier to hide it.",
back: Color("Theme3ForegroundColor"),
textColor: Color("Theme3BackgroundColor"))
Spacer()
}
.font(.title)
.padding(.top, 70)
}
// Hide when the Toggle is on Notice the navigationBarHidden modifier
.navigationBarHidden(isHidden)
.ignoresSafeArea(edges: .bottom) is INSIDE the NavigationView.
}
}
}
www.bigmountainstudio.com 153
NavigationView
HeaderView("NavigationView",
subtitle: "Navigation Bar Items",
desc: "You can add navigation bar buttons to the leading or trailing
(or both) sides of a navigation bar.",
back: Color("Theme3ForegroundColor"),
textColor: Color("Theme3BackgroundColor"))
Spacer()
}
.font(.title)
.padding(.top, 25)
.navigationTitle("Navigation Bar Buttons")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
For more ways on how to use
ToolbarItem(placement: .navigationBarLeading) {
Button(action: {}) { the toolbar modifier, go to the
Image(systemName: "bell.fill")
“Controls Modifiers” chapter >
.padding(.horizontal)
} “Toolbar” section.
}
ToolbarItem(placement: .navigationBarTrailing) {
Button("Actions", action: { })
}
}
}
.accentColor(.pink) Use the accentColor on the NavigationView to
}
} change the color of the buttons.
www.bigmountainstudio.com 154
NavigationView
NavigationBarBackButtonHidden
www.bigmountainstudio.com 155
NavigationView
NavigationBarBackButtonHidden - Code
// First Screen
struct Navigation_BackButtonHidden: View {
var body: some View {
NavigationView {
ZStack {
Color("Theme3BackgroundColor")
VStack(spacing: 25) {
Image(systemName: "globe").font(.largeTitle)
Text("NavigationView").font(.largeTitle)
Text("Back Button Hidden").foregroundColor(.gray)
Image("NavBarBackButtonHidden") Use NavigationLink to navigate
to a new screen.
NavigationLink("Go To Detail", destination: BackButtonHiddenDetail())
More about NavigationLink in the
Spacer()
} next section.
.font(.title)
.padding(.top, 70)
}
.navigationTitle("Navigation Views")
.ignoresSafeArea(edges: .bottom)
}
}
}
// Second Screen
struct BackButtonHiddenDetail: View { This will allow you
@Environment(\.presentationMode) var presentationMode to navigate
backward.
var body: some View {
www.bigmountainstudio.com 156
NavigationView
NavigationBarBackButtonHidden - Code
ZStack {
Color("Theme3BackgroundColor")
VStack(spacing: 25) {
Image(systemName: "globe").font(.largeTitle)
Text("NavigationView").font(.largeTitle)
Text("Back Button Hidden").foregroundColor(.gray)
Image("NavBarBackButtonHidden")
Text("This nav bar has no back button because it was hidden on this view.")
.frame(maxWidth: .infinity)
.padding()
.background(Color("Theme3ForegroundColor"))
.foregroundColor(Color("Theme3BackgroundColor"))
Button("Go Back") {
self.presentationMode.wrappedValue.dismiss()
}
Dismissing what is being presented will
Spacer()
navigate you back to the previous view.
}
.font(.title)
.padding(.top, 50)
}
.navigationTitle("Detail View")
.navigationBarTitleDisplayMode(.inline)
.ignoresSafeArea(edges: .bottom)
// Hide the back button
.navigationBarBackButtonHidden(true) Hide the back button.
}
}
www.bigmountainstudio.com 157
NavigationView
www.bigmountainstudio.com 158
NavigationLink
NavigationLink
The NavigationLink is your way to navigate to another view. It ONLY works inside of a NavigationView. The appearance is
just like a Button. You can customize it just like you can customize a Button too.
www.bigmountainstudio.com 159
NavigationLink
Introduction
struct NavLink_Intro: View {
var body: some View {
NavigationView {
VStack(spacing: 20) {
HeaderView("",
subtitle: "Introduction",
desc: "Use NavigationLink to navigate to a new view inside a
NavigationView.",
back: Color("Theme3ForegroundColor"),
textColor: Color("Theme3BackgroundColor"))
NavigationLink("Just Text", destination: SecondView())
Spacer()
DescView(desc: "This is the basic implementation using just text and a
destination. The destination can be any view.",
back: Color("Theme3ForegroundColor"),
textColor: Color("Theme3BackgroundColor"))
}
.navigationTitle("NavigationLink")
} Define text and a view for the
.font(.title)
}
destination.
}
www.bigmountainstudio.com 160
NavigationLink
Customization
struct NavLink_Customization: View {
var body: some View {
NavigationView {
VStack(spacing: 20) {
HeaderView("",
subtitle: "Customization",
desc: "You can customize NavigationLink just like you would with a
Button.",
back: Color("Theme3ForegroundColor"),
textColor: Color(“Theme3BackgroundColor"))
NavigationLink(destination: SecondView()) {
Text("Navigate")
.foregroundColor(.white)
.padding()
.background(RoundedRectangle(cornerRadius: 16)
.shadow(radius: 10, y: 15))
}
.accentColor(.pink)
NavigationLink(destination: SecondView()) {
HStack {
Text("Navigate") The trailing closure is the
Spacer()
label parameter. This allows
Image(systemName: "chevron.right")
} you to compose any view
.padding()
} that will navigate you.
Spacer()
}
.navigationTitle("NavigationLink")
}
.font(.title)
} Tip: Try to keep your views and modifiers within the closure.
}
Like the Button, anything inside will fade when tapped.
www.bigmountainstudio.com 161
NavigationLink
With isActive
struct NavLink_WithIsActive: View {
@State var nav = false
The NavigationLink here has no visual
representation so you won’t see it in the UI.
var body: some View {
NavigationView {
VStack {
HeaderView("NavigationLink",
subtitle: "With isActive",
desc: "You can automatically have a NavigationLink navigate to
another view using a boolean.",
back: Color("Theme3ForegroundColor"),
textColor: Color("Theme3BackgroundColor"))
Text("AutoNav is: \(nav.description)")
www.bigmountainstudio.com 162
NavigationLink
www.bigmountainstudio.com 163
NavigationLink
www.bigmountainstudio.com 164
NavigationLink
www.bigmountainstudio.com 165
NavigationLink
With selection
struct NavLink_WithSelection: View {
@State var nav: String? Basically, when the selection parameter value matches the
value of the tag parameter, navigation happens.
var body: some View {
NavigationView {
VStack {
HeaderView("NavigationLink",
subtitle: "With selection",
desc: "You can automatically have a NavigationLink navigate to
another view using a specified value. When the tag parameter matches the selection parameter,
navigation will happen.",
back: Color("Theme3ForegroundColor"),
textColor: Color("Theme3BackgroundColor"))
www.bigmountainstudio.com 166
NavigationLink
www.bigmountainstudio.com 167
NavigationLink
www.bigmountainstudio.com 168
NavigationLink
www.bigmountainstudio.com 169
NavigationLink
Without getting too technical, the NavigationLink isn’t the type of view that SwiftUI knows when and
when not to recreate. So it is recreated all the time. Xcode will not warn you against this. And, whether
intentional or a bug, it can navigate multiple times or not at all depending on the iOS version.
It might look like it works in Preview, but be sure to test on Simulator and on a device.
Workaround: There is another way around this though which you will see on the next page.
www.bigmountainstudio.com 170
NavigationLink
www.bigmountainstudio.com 171
NavigationLink
www.bigmountainstudio.com 172
NavigationLink
www.bigmountainstudio.com 173
NavigationLink
www.bigmountainstudio.com 174
NavigationLink
Pop to Root
struct NavLink_PopToRoot: View {
@State private var isActive = false
NavigationLink(
destination: NavLinkView2(isActive: $isActive),
isActive: $isActive,
label: {
Text("Navigate to View 2")
})
The key is to use this
} isActive parameter and then
.navigationTitle("NavigationLink") pass that value to the views
.font(.title) that should pop back to the
}
root.
}
}
www.bigmountainstudio.com 175
NavigationLink
www.bigmountainstudio.com 176
iOS 14
OutlineGroup
SwiftUI 2 (iOS 14) content is locked in this preview. This is everything you get:
The complete SwiftUI Views Mastery book (PDF & ePub)
BONUS: The FULL Xcode Project ($997 Value)
BONUS: SwiftUI Views Study Guide ($97 Value)
OutlineGroups gives you another way to present hierarchical data. It is very similar to using a List with the children
BONUS: SwiftUI Views Flashcard Decks ($47 Value)
parameter. Except this container view does not scroll. It’s probably best for limited data.
BONUS: My Personal Xcode Editor Theme ($17 Value)
This is a pull-in view. UNLOCK THE BOOK BUNDLE TODAY FOR ONLY $55!
www.bigmountainstudio.com 177
Picker
To get or set a value for the Picker, you need to bind it to a variable. This variable is then passed into the Picker’s initializer.
Then, all you need to do is change this bound variable’s value to select the row you want to show in the Picker. Or read the
bound variable’s value to see which row is currently selected. One thing to note is that this variable is actually bound to the
Picker row’s tag property which you will see in the following pages.
www.bigmountainstudio.com 178
Picker
Introduction
struct Picker_Intro : View {
@State private var favoriteState = 1
@State private var yourName = "Mark"
var body: some View {
VStack(spacing: 20) {
Text("Picker").font(.largeTitle)
Text("Introduction").font(.title).foregroundColor(.gray)
www.bigmountainstudio.com 179
Picker
Customized
struct Picker_Customized : View {
@State private var favoriteState = 1
@State private var youTuberName = "Mark"
var body: some View {
VStack(spacing: 30) {
Text("Picker").font(.largeTitle)
Text("With Modifiers").foregroundColor(.gray)
Text("Your Favorite State:")
Picker(selection: $favoriteState, label: Text("")) {
Text("California").tag(0)
Text("Utah").tag(1)
Text("Vermont").tag(2)
}
.foregroundColor(Color.white).padding(.horizontal)
.background(Color("AccentColorDark"))
.cornerRadius(15)
.shadow(radius: 5)
Text("Who do you want to watch today?")
Picker(selection: $youTuberName, label: Text("")) {
Text("Paul").tag("Paul")
Text("Chris").tag("Chris")
Text("Mark").tag("Mark")
Text("Scott").tag("Scott")
Text("Meng").tag("Meng")
}
.padding(.horizontal)
.background(RoundedRectangle(cornerRadius: 15)
.stroke(Color.blue, lineWidth: 1))
}
.labelsHidden() // Show no labels on pickers
.font(.title)
}
}
www.bigmountainstudio.com 180
Picker
www.bigmountainstudio.com 181
Picker
www.bigmountainstudio.com 182
iOS 14
ProgressView
SwiftUI 2 (iOS 14) content is locked in this preview. This is everything you get:
The complete SwiftUI Views Mastery book (PDF & ePub)
BONUS: The FULL Xcode Project ($997 Value)
BONUS: SwiftUI Views Study Guide ($97 Value)
The progress view gives you a few different ways to show the user that something is currently happening and optionally
BONUS: SwiftUI Views Flashcard Decks ($47 Value)
give you a way to show the progression of BONUS:
some activity.
My Personal Xcode Editor Theme ($17 Value)
183
ScrollView
A ScrollView is like a container for child views. When the child views within the ScrollView go outside the frame, the user can
scroll to bring the child views that are outside the frame into view.
A ScrollView is a push-out view in the scroll direction you specify. You can set the direction of a ScrollView to be vertical or
horizontal.
www.bigmountainstudio.com 184
ScrollView
Introduction
@State private var names = ["Scott", "Mark", "Chris", "Sean", "Rod", "Meng", "Natasha", "Chase",
"Evans", "Paul", "Durtschi", "Max"]
...
NavigationView {
GeometryReader { gr in
ScrollView {
ForEach(self.names, id: \.self) { name in
NavigationLink(destination: DetailView(name: name)) {
HStack {
Text(name).foregroundColor(.primary)
Image(systemName: "checkmark.seal.fill")
.foregroundColor(.green)
Spacer()
Image(systemName: "chevron.right.circle.fill")
}
.font(.system(size: 24, design: .rounded))
.padding().background(Color.white)
.cornerRadius(8)
.shadow(radius: 1, y: 1)
}
} // Set the width on the ForEach (it's a View)
.frame(width: gr.size.width - 32)
.accentColor(Color.pink)
.padding()
}
.navigationBarTitle(Text("Cool People"))
}
}
A Scrollview with a ForEach view is similar to a List. But be warned, the rows are not reusable. It is best to limit
the number of rows for memory and performance considerations.
www.bigmountainstudio.com 185
ScrollView
Scroll Horizontally
struct Scrollview_Horizontal : View {
var items = [Color.green, Color.blue, Color.purple, Color.pink,
Color.yellow, Color.orange]
www.bigmountainstudio.com 186
SecureField
In order to get or set the text in a SecureField, you need to bind it to a variable. This variable is passed into the SecureField’s
initializer. Then, all you need to do is change this bound variable’s text to change what is in the SecureField. Or read the
bound variable’s value to see what text is currently in the SecureField.
www.bigmountainstudio.com 187
SecureField
Introduction
@State private var userName = ""
@State private var password = ""
...
VStack(spacing: 20) {
Image("Logo")
.padding(.bottom, 150)
Text("SecureField")
.font(.largeTitle)
Text("Introduction")
.font(.title)
.foregroundColor(.gray)
Spacer()
}
www.bigmountainstudio.com 188
SecureField
Customizations
@State private var userName = ""
@State private var password = ""
...
ZStack{
RoundedRectangle(cornerRadius: 8)
.foregroundColor(.purple)
TextField("user name", text: $userName)
.foregroundColor(Color.white)
.padding(.horizontal)
}
.frame(height: 40)
.padding(.horizontal)
RoundedRectangle(cornerRadius: 8)
.foregroundColor(.purple)
.overlay(
SecureField("password", text: $password)
.foregroundColor(Color.white)
.padding(.horizontal)
)
.frame(height: 40)
.padding(.horizontal)
www.bigmountainstudio.com 189
SecureField
Customization Layers
@State private var userName = ""
@State private var password = ""
...
VStack(spacing: 20) {
Text("SecureField")
.font(.largeTitle)
Text("Customization Layers")
.font(.title)
.foregroundColor(.gray)
Text("You can also add a background to the SecureField. It's all the same idea: adjust the
layers.")
...
Image("SecureFieldLayers")
Text("The highlighted layer in that image is the actual text field layer of the view.")
.font(.title)
.padding(.horizontal)
}
www.bigmountainstudio.com 190
Segmented controls are now Picker controls with a different picker style set. In order to get or set the selected segment, you
need to bind it to a variable. This variable is passed into the segmented control’s (Picker’s) initializer. Then, all you need to
do is change this bound variable’s value to change the selected segment. Or read the bound variable’s value to see which
segment is currently selected.
www.bigmountainstudio.com 191
Introduction
@State private var dayNight = "day"
@State private var tab = 1
...
VStack(spacing: 20) {
Text("Segmented Control (Picker)").font(.largeTitle)
Text("Introduction")
.font(.title).foregroundColor(.gray)
Text("Associate the segmented control with an @State variable that will control which
segment is selected. The state variable will match each segment's tag value.")
...
Text("With Images:")
www.bigmountainstudio.com 192
No Segment Selected
@State private var selection = 0
...
VStack(spacing: 20) {
Text("Segmented Control (Picker)").font(.largeTitle)
Text("No Segment Selected")
.font(.title).foregroundColor(.gray)
Text("This segmented control will have nothing selected because the default state variable
does not match any of the segment tag values.")
...
www.bigmountainstudio.com 193
Colors
@State private var selection = 2
...
VStack(spacing: 20) {
Text("Segmented Control (Picker)").font(.largeTitle)
Text("Colors")
.font(.title).foregroundColor(.gray)
Text("You can change the color of segmented controls by using the background modifier.")
...
www.bigmountainstudio.com 194
iOS 14
SignInWithAppleButton
!
SwiftUI 2 (iOS 14) content is locked in this preview. This is everything you get:
The complete SwiftUI Views Mastery book (PDF & ePub)
BONUS: The FULL Xcode Project ($997 Value)
BONUS: SwiftUI Views Study Guide ($97 Value)
Apple provides you with a button that you use in your app to assist your users when it comes time to implementing signing
BONUS: SwiftUI Views Flashcard Decks ($47 Value)
in with Apple. BONUS: My Personal Xcode Editor Theme ($17 Value)
This is a push-out view. UNLOCK THE BOOK BUNDLE TODAY FOR ONLY $55!
www.bigmountainstudio.com 195
Slider
When using a Slider view, the default range of values is 0.0 to 1.0. You bind the Slider to a state variable, usually a number
type, like an Int. But it doesn’t have to be a number type. It can be any type that conforms to the Stridable protocol. (“Stride”
means to “take steps in a direction; usually long steps”.) A type that conforms to Stridable (such as an Int) means it has
values that are continuous and can be stepped through and measured. (“Step through”, “Stride”, I think you see the
connection now.)
You use the bound variable to set or get the value the Slider’s thumb (circle) is currently at.
www.bigmountainstudio.com 196
Slider
Introduction
struct Slider_Intro : View {
@State private var sliderValue = 0.5 Value used for the slider.
}.font(.title)
}
}
www.bigmountainstudio.com 197
Slider
www.bigmountainstudio.com 198
Slider
Customization
@State private var sliderValue = 0.5
...
Text("At the time of this writing, there isn't a way to color the thumb. But we can change the
background color and apply some other modifiers.")
...
Slider(value: $sliderValue)
.padding(.horizontal, 10)
.background(Color.orange)
.cornerRadius(.infinity) // Rounded ends
.shadow(color: .gray, radius: 2)
.padding(.horizontal)
Slider(value: $sliderValue)
.padding(.horizontal)
.accentColor(.orange)
Slider(value: $sliderValue)
.padding(10)
.background(Capsule().stroke(Color.orange, lineWidth: 2))
.padding(.horizontal)
Slider(value: $sliderValue)
.padding(10)
.background(Capsule().fill(Color.orange))
.accentColor(.black)
.padding(.horizontal)
www.bigmountainstudio.com 199
Slider
With Images
Text("Combine the slider with images in an HStack, VStack or both!")
...
HStack {
Image(systemName: "tortoise")
Slider(value: $sliderValue)
Image(systemName: "hare")
}.foregroundColor(.green).padding()
HStack {
Image(systemName: "speaker.fill")
Slider(value: $sliderValue)
Image(systemName: "speaker.3.fill")
}
.foregroundColor(.accentColor)
.padding()
VStack {
Slider(value: $sliderValue)
.accentColor(.orange)
HStack {
Image(systemName: "circle")
Spacer()
Image(systemName: "circle.righthalf.fill")
Spacer()
Image(systemName: "circle.fill")
}
.foregroundColor(.orange)
.padding(.top, 8)
}.padding()
www.bigmountainstudio.com 200
Stepper
When using a Stepper view, you bind it to a state variable, usually a number. But it doesn’t have to be a number type. It can
be any type that conforms to the Stridable protocol. (“Stride” means to “take steps in a direction; usually long steps”.) A type
that conforms to Stridable means it has values that are continuous and can be stepped through and measured. (“Step
through”, “Stride”, I think you see the connection now.)
You use the bound variable to set or get the value it is currently at.
This is a horizontal push-out view. Vertically it is pull-in.
www.bigmountainstudio.com 201
Stepper
Introduction
@State private var stepperValue = 1
@State private var values = [0, 1]
...
VStack(spacing: 20) {
Text("Stepper")
.font(.largeTitle)
Text("Introduction")
.font(.title).foregroundColor(.gray)
Text("The Stepper can be bound to a variable like this:")
...
Stepper(value: $stepperValue) {
Text("Bound Stepper: \(stepperValue)")
}.padding(.horizontal)
Divider()
Image(systemName: "bolt.fill")
.font(.title).foregroundColor(.yellow)
Text("Or you can run code on the increment and decrement events:")
.frame(maxWidth: .infinity).padding()
.background(Color.blue).foregroundColor(Color.white)
.font(.title)
Stepper(onIncrement: {self.values.append(self.values.count)},
onDecrement: {self.values.removeLast()}) {
Text("onIncrement and onDecrement")
}.padding(.horizontal)
HStack {
ForEach(values, id: \.self) { value in
Image(systemName: "\(value).circle.fill")
}
}.font(.title).foregroundColor(.green)
}
www.bigmountainstudio.com 202
Stepper
Label Options
struct Stepper_LabelsHidden: View {
@State private var stepperValue = 1
Note: Even though the label/title is not shown, I would still recommend having one because it will still be used
for accessibility purposes.
www.bigmountainstudio.com 203
Stepper
Range
@State private var stars = 0
VStack(spacing: 20) {
Text("Stepper")
.font(.largeTitle)
.padding()
Text("Range of Values")
.font(.title)
.foregroundColor(.gray)
Text("You can set a range for the stepper too. In this example, the range is between one and
five.")
...
HStack {
ForEach(1...stars, id: \.self) { star in
Image(systemName: "star.fill")
}
}
.font(.title)
.foregroundColor(.yellow)
}
When the Stepper reaches the range limits, the corresponding plus or minus button will appear as disabled. In
this screenshot, notice the plus button is disabled.
www.bigmountainstudio.com 204
Stepper
Customization
@State private var contrast = 50
...
Text("A foreground and background color can be set.")
...
Text("Notice the minus and plus buttons are not affected. The platforms determine how this will
be shown.")
...
www.bigmountainstudio.com 205
Stepper
Colors
Text("There is no built-in way to change the color of the stepper that I have found. Instead, I
had to hide the label and apply a color behind it.”)
...
HStack {
Text("My Custom Colored Stepper")
Spacer()
Stepper("", value: $contrast)
.background(Color(UIColor.systemTeal))
.cornerRadius(9)
.labelsHidden() // Hide the label
}
HStack {
Text("My Custom Colored Stepper")
Spacer()
Stepper("", value: $contrast)
.background(Color.orange)
.cornerRadius(9)
.labelsHidden() // Hide the label
}
www.bigmountainstudio.com 206
TabView
The TabView acts like a container for child views within it. These child views are individual screens. It provides tab buttons
(TabItems) that allows the user to switch between these child views.
www.bigmountainstudio.com 207
TabView
Introduction
TabView {
// First Screen
VStack(spacing: 20) {
Text("TabView")
.font(.largeTitle)
Text("Introduction")
.font(.title)
.foregroundColor(.gray)
Text("The TabView view can hold multiple views, one for each tab.")
...
Text("At the end of a view, you add .tabItem modifier to show a button that allows
navigation to that view.")
...
Image("TabItem")
}.tabItem {
// Creates a tab button in the tab bar
Text("Tab 1")
}
// Second Screen
Text("This view represents the Second Screen.")
.tabItem {
// Creates a tab button in the tab bar
Text("Tab 2")
}
}
www.bigmountainstudio.com 208
TabView
TabItems
struct TabView_Tabs : View {
var body: some View {
TabView {
TabOne().tabItem {
Text("Tab Text")
}
Text("Phone Calls").tabItem {
Image(systemName: "phone")
}
Text("Outgoing Phone Calls").tabItem {
Image(systemName: "phone.arrow.up.right")
Text("Outgoing")
}
}
}
}
www.bigmountainstudio.com 209
TabView
When there are too many tabs to fit for the device, the More button is created where you can find the
rest of the tabs listed out.
www.bigmountainstudio.com 210
TabView
Navigation
@State private var selectedTab = 1 // Set which tab is active
...
// Tell the TabView which variable to listen to for changes
TabView(selection: $selectedTab) {
// Tab 1
VStack(spacing: 20) {
Text("TabView").font(.largeTitle)
Text("Navigation")
.font(.title).foregroundColor(.gray)
Text("Add a unique tag value to each screen (view) you want to programmatically navigate
to. You can then bind a variable to the TabView's selection property and change that variable to
navigate.")
...
}.tabItem {
Image(systemName: "star.fill")
}.tag(1)
// Tab 2
Text("Second Screen")
.tabItem {
Image(systemName: "moon.fill")
}.tag(2)
// Tab 3
Text("Third Screen")
.tabItem {
Image(systemName: "sun.min.fill")
}.tag(3)
}
www.bigmountainstudio.com 211
TabView
Colors
TabView {
// Tab 1
ZStack {
Color.blue.colorMultiply(.red).edgesIgnoringSafeArea(.top)
VStack(spacing: 20) {
Text("TabView")
.font(.largeTitle).foregroundColor(.white)
Text("TabItem Colors")
.font(.title).foregroundColor(.gray)
Text("Set the color of the active tab item by setting the accent color for the
TabView.")
...
}
}.tabItem {
Image(systemName: "star.fill")
}
// Tab 2
Text("Second Screen").tabItem {
Image(systemName: "moon.fill")
}.foregroundColor(Color.red)
// Tab 3
Text("Third Screen").tabItem {
Image(systemName: "sun.min.fill")
}
}
.edgesIgnoringSafeArea(.top)
.accentColor(.yellow)
Notice that I am setting the foreground color of the second tabItem to red. This will have no effect on
the color of the tab item. The background modifier will not work either.
www.bigmountainstudio.com 212
iOS 14
SwiftUI 2 (iOS 14) content is locked in this preview. This is everything you get:
The complete SwiftUI Views Mastery book (PDF & ePub)
BONUS: The FULL Xcode Project ($997 Value)
BONUS: SwiftUI Views Study Guide ($97 Value)
With the existing TabView, SwiftUI now offers a new style for it that allows the views within a TabView to be able to be
BONUS: SwiftUI Views Flashcard Decks ($47 Value)
swiped horizontally and “snap” into place when the view enters the screen.
BONUS: My Personal Xcode Editor Theme ($17 Value)
This is a push-out view. UNLOCK THE BOOK BUNDLE TODAY FOR ONLY $55!
www.bigmountainstudio.com 213
Text
The text view will probably be one of your most-used views. It has many, if not the most, modifiers available to it.
www.bigmountainstudio.com 214
Text
Line Limit
VStack(spacing: 20) {
Text("Text")
.font(.largeTitle)
Text("Wrapping")
.font(.title)
.foregroundColor(.gray)
Image("LineLimit")
Text("The Text view shows read-only text that can be modified in many ways. It wraps
automatically. If you want to limit the text wrapping, add .lineLimit(<number of lines here>).")
...
www.bigmountainstudio.com 215
Text
Text Styles
VStack(spacing: 20) {
Text("Text")
.font(.largeTitle)
Text("Text Styles")
.font(.title)
.foregroundColor(.gray)
Image("Font")
Text("You can add a TextStyle to the Text view by calling .font(Font.<Text Style>).")
...
Group {
Divider()
Text("Font.largeTitle").font(.largeTitle)
Text("Font.title").font(.title)
Text("Font.headline").font(.headline)
Text("Font.subheadline").font(.subheadline)
Text("Font.body").font(.body)
Text("Font.callout").font(.callout)
Text("Font.caption").font(.caption)
Text("Font.footnote").font(.footnote)
}
}
www.bigmountainstudio.com 216
Text
Weights
Text("Text")
.font(.largeTitle)
Text("Font Weights")
.font(.title)
.foregroundColor(.gray)
Image("FontWeight")
Text("You can apply a variety of font weights to the Text view.")
.padding()
.frame(maxWidth: .infinity)
.background(Color.green)
.foregroundColor(.white)
.font(.title)
.layoutPriority(2)
Group { // Too many views (> 10) in one container
Text("Ultralight")
.fontWeight(.ultraLight)
Text("Thin")
.fontWeight(.thin)
Text("Light")
.fontWeight(.light)
Text("Regular")
.fontWeight(.regular)
Text("Medium")
.fontWeight(.medium)
Text("Semibold")
.fontWeight(.semibold)
Text("Bold")
.fontWeight(.bold)
Text("Heavy")
.fontWeight(.heavy)
Text("Black")
.fontWeight(.black)
}.font(.title)
www.bigmountainstudio.com 217
Text
Text("Ultralight - Title")
.fontWeight(.ultraLight)
.font(.title)
Text("Thin - Body")
.fontWeight(.thin)
.font(.body)
Text("Light - Large Title")
.fontWeight(.light)
.font(.largeTitle)
Text("Bold - Callout")
.fontWeight(.bold)
.font(.callout)
Text("Black - Title")
.fontWeight(.black)
.font(.title)
}
.edgesIgnoringSafeArea(.bottom)
www.bigmountainstudio.com 218
Text
Font Design
VStack(spacing: 20) {
Text("Text")
.font(.largeTitle)
Text("Font Design")
.font(.title)
.foregroundColor(.gray)
Text("There are 4 font designs now in iOS. Use Font.system to set the font design you
want.")
...
www.bigmountainstudio.com 219
Text
Formatting
@State private var modifierActive = true
...
HStack {
Image("Bold")
Text("Bold").bold()
}
HStack {
Image("Italic")
Text("Italic").italic()
}
HStack {
Image("Strikethrough")
Text("Strikethrough").strikethrough()
}
HStack {
Image("Strikethrough")
Text("Green Strikethrough")
.strikethrough(modifierActive, color: .green)
}
HStack {
Image("ForegroundColor")
Text("Text Color (ForegroundColor)").foregroundColor(.green)
}
HStack {
Image("Underline")
Text("Underline").underline()
}
HStack {
Image("Underline")
Text("Green Underline").underline(modifierActive, color: .green)
}
...
Toggle("Modifiers Active", isOn: $modifierActive)
www.bigmountainstudio.com 220
Text
Allows Tightening
VStack(spacing: 20) {
...
Image("AllowsTightening")
Text("You might want to tighten up some text that might be too long.")
...
Group {
Text("Allows tightening to allow text to fit in one line.")
.foregroundColor(.red)
.allowsTightening(false)
.padding(.horizontal)
.lineLimit(1)
Text("Allows tightening to allow text to fit in one line.")
.foregroundColor(.green)
.allowsTightening(true)
.padding(.horizontal)
.lineLimit(1)
}.padding(.horizontal)
}
Allows Tightening can be helpful when you see the last word getting truncated. Applying it may not
even fully work depending on just how much space can be tightened. With the default font, I notice I can
get a couple of characters worth of space to tighten up.
www.bigmountainstudio.com 221
Text
Text("Allows tightening is failing here because the text is too long. In this case, you can
apply a minimum scale factor and specify by how much you want to allow the text to shrink.")
...
Image("MinimumScaleFactor")
Text(".minimumScaleFactor(0.5) is being used here:")
...
Text(".minimumScaleFactor takes a fraction from 0 to 1. For example, 0.3 is 30% of the original
size of the font that it can shrink. If the font size is 100, then it can shrink to 30.")
www.bigmountainstudio.com 222
Text
Line Spacing
VStack(spacing: 10) {
Text("Text").font(.largeTitle)
Text("Line Spacing").font(.title).foregroundColor(.gray)
Image("LineSpacing")
Text("You can use line spacing to add more space between lines of text. This text has no
line spacing applied:")
.font(.title)
.frame(maxWidth: .infinity)
.padding()
.background(Color.green)
.foregroundColor(Color.white)
.layoutPriority(1)
Text("SwiftUI offers a Line Spacing modifier for situations where you want to increase the
space between the lines of text on the screen.")
.font(.title)
Text("SwiftUI offers a Line Spacing modifier for situations where you want to increase the
space between the lines of text on the screen.")
.lineSpacing(16.0) // Add spacing between lines
.font(.title)
}
www.bigmountainstudio.com 223
Text
Alignment
VStack(spacing: 20) {
Text("Text").font(.largeTitle)
Text("Multiline Text Alignment").foregroundColor(.gray)
Image("MultilineTextAlignment")
Text("By default, text will be centered within the screen. But when it wraps to multiple
lines, it will be leading aligned by default. Use multilineTextAlignment modifier to change
this!")
...
Text(".multilineTextAlignment(.center)")
.frame(maxWidth: .infinity)
.padding()
.foregroundColor(.white)
.background(Color.green)
Text(".multilineTextAlignment(.trailing)")
.frame(maxWidth: .infinity)
.padding()
.foregroundColor(.white)
.background(Color.green)
.allowsTightening(true) // Prevent truncation
Text("You are SUPER awesome for improving your skills by using this book!")
.multilineTextAlignment(.trailing) // Trailing align
.padding(.horizontal)
}
.font(.title) // Apply this text style to all text views
www.bigmountainstudio.com 224
Text
Truncation Mode
VStack(spacing: 20) {
Text("Text").font(.largeTitle)
Text("Truncation Mode").font(.title).foregroundColor(.gray)
Image("TruncationMode")
Text("When text gets truncated, you can control where the ellipsis (...) shows.")
.frame(maxWidth: .infinity).padding()
.foregroundColor(.white).background(Color.green)
.font(.title)
Text("Default: .truncationMode(.tail)")
.frame(maxWidth: .infinity).padding()
.foregroundColor(.white).background(Color.green)
.font(.title)
// Text automatically defaults at end
Text("This will be the best day of your life!")
.padding(.horizontal)
.lineLimit(1)
Text(".truncationMode(.middle)")
.frame(maxWidth: .infinity).padding()
.foregroundColor(.white).background(Color.green)
Text("This will be the best day of your life!")
.truncationMode(.middle) // Truncate in middle
.padding(.horizontal)
.lineLimit(1)
Text(".truncationMode(.head)")
.frame(maxWidth: .infinity).padding()
.foregroundColor(.white).background(Color.green)
Text("This will be the best day of your life!")
.truncationMode(.head) // Truncate at beginning
.padding(.horizontal)
.lineLimit(1)
}
.font(.title)
www.bigmountainstudio.com 225
Text
Group {
Text("You can also ").font(.title).fontWeight(.light)
+ Text("combine")
+ Text(" different font weights ").fontWeight(.black)
+ Text("and different text styles!").font(.title).fontWeight(.ultraLight)
}
.padding(.horizontal)
Although you see I’m wrapping my Text views in a Group, it is not required. I only do this so I can apply common
modifiers to everything within the Group. See section on the Group view for more information.
www.bigmountainstudio.com 226
Text
Baseline Offset
VStack(spacing: 20) {
Text("Text")
.font(.largeTitle)
Text("Baseline Offset")
.font(.title).foregroundColor(.gray)
Image("BaselineOffset")
Text("By default, your combined text will be on the same baseline, like this:")
...
Text("100").underline()
+ Text(" SWIFTUI ").font(.largeTitle).fontWeight(.light)
.foregroundColor(.blue).underline()
+ Text ("VIEWS").underline()
Text("But you can offset each text view to create a cooler effect, like this:")
...
Group {
Text("100").bold()
+ Text(" SWIFTUI ")
.font(Font.system(size: 60))
.fontWeight(.ultraLight)
.foregroundColor(.blue)
.baselineOffset(-12) // Negative numbers go down
+ Text ("VIEWS").bold()
}
.layoutPriority(2)
}
www.bigmountainstudio.com 227
Text
Layout Priority
Text("Text")
.font(.largeTitle)
Text("Layout Priority")
.font(.title)
.foregroundColor(.gray)
Image("LayoutPriority")
Text("Layout priority controls which view will get truncated last. The higher the priority, the
last it is in line to get truncated.")
.font(.title)
.foregroundColor(.white)
.frame(maxWidth: .infinity)
.padding()
.background(Color.green)
.layoutPriority(2) // Highest priority to get the space it needs
Text("The text view above got truncated because its layout priority is zero (the default). This
text view has a priority of 1. The text view on top has a priority of 2.")
.font(.title)
.foregroundColor(.white)
.frame(maxWidth: .infinity)
.padding()
.background(Color.green)
.layoutPriority(1) // Next highest priority
www.bigmountainstudio.com 228
Text
Custom Fonts
Text("Use a font that already exists on the system. If the font name doesn't exist, it goes back
to the default font.")
...
Text("This font doesn't exist")
.font(Font.custom("No Such Font", size: 26))
Text("Existing fonts:")
...
Text("Avenir Next")
.font(Font.custom("Avenir Next", size: 26))
Text("Gill Sans")
.font(Font.custom("Gill Sans", size: 26))
Text("Helvetica Neue")
.font(Font.custom("Helvetica Neue", size: 26))
www.bigmountainstudio.com 229
Text
Imported Fonts
struct Text_CustomFont: View {
var body: some View {
VStack(spacing: 20) {
Text("Text")
.font(.largeTitle)
Text("Imported Fonts")
.font(.title)
.foregroundColor(.gray)
Text("Use the Font.custom() function to set imported fonts you added to your
project.")
...
Text("Hello, World!")
.font(Font.custom("Nightcall", size: 60))
.padding(.top)
}
}
}
In order for this to work, you have to add the font file to your project and be sure to have the font file
target your project. Then you need to add the font file name to the Info.plist under the “Fonts provided
by application” key:
www.bigmountainstudio.com 230
iOS 14
TextEditor
Text
SwiftUI 2 (iOS 14) content is locked in this preview. This is everything you get:
The complete SwiftUI Views Mastery book (PDF & ePub)
BONUS: The FULL Xcode Project ($997 Value)
BONUS: SwiftUI Views Study Guide ($97 Value)
BONUS: SwiftUI Views Flashcard Decks ($47 Value)
You can use the TextEditor to provide text BONUS:
input from users that goes beyond just one line.
My Personal Xcode Editor Theme ($17 Value)
This is a push-out view. UNLOCK THE BOOK BUNDLE TODAY FOR ONLY $55!
www.bigmountainstudio.com 231
TextField
In order to get or set the text in a TextField, you need to bind it to a variable. This variable is passed into the TextField’s
initializer. Then, all you need to do is change this bound variable’s text to change what is in the TextField. Or read the bound
variable’s value to see what text is currently in the TextField.
www.bigmountainstudio.com 232
TextField
Introduction
struct TextField_Intro : View {
@State private var textFieldData = ""
Text("By default, TextFields have a plain TextFieldStyle that has no visual content
to be seen.")
.frame(maxWidth: .infinity).padding()
.background(Color.orange)
Image(systemName: "arrow.down.circle")
TextField("", text: $textFieldData)
Image(systemName: "arrow.up.circle")
Text("Use .textFieldStyle(RoundedBorderTextFieldStyle()) to show a border.")
.frame(maxWidth: .infinity).padding()
.background(Color.orange)
TextField("", text: $textFieldData)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding(.horizontal)
}.font(.title)
}
}
www.bigmountainstudio.com 233
TextField
Text("You can supply title text (placeholder/hint text) through the first parameter
to let the user know the purpose of the text field.")
.frame(maxWidth: .infinity).padding()
.background(Color.orange)
Group {
TextField("Here is title text", text: $textFieldData)
.textFieldStyle(RoundedBorderTextFieldStyle())
www.bigmountainstudio.com 234
TextField
Text Alignment
struct TextField_Alignment: View {
@State private var textFieldData1 = "Leading"
@State private var textFieldData2 = "Center"
@State private var textFieldData3 = "Trailing"
Group {
TextField("Leading", text: $textFieldData1)
.textFieldStyle(RoundedBorderTextFieldStyle())
.multilineTextAlignment(.leading) // Default
www.bigmountainstudio.com 235
TextField
Text("Notice this also changes the placeholder or hint text in the text field.")
.frame(maxWidth: .infinity)
.padding()
.background(Color.orange)
}.font(.title)
}
}
www.bigmountainstudio.com 236
TextField
Customizing Colors
struct TextField_Customizing : View {
@State private var textFieldWithText = "With Text"
@State private var textFieldNoText = ""
@State private var withOutline = "With Outline"
www.bigmountainstudio.com 237
TextField
Group {
// First TextField
ZStack(alignment: .leading) {
// Only show custom hint text if there is no text entered
if textFieldData.isEmpty {
Text("Enter name here").bold()
.foregroundColor(Color(.systemGray4))
}
TextField("", text: $textFieldData)
}
.padding(EdgeInsets(top: 4, leading: 10, bottom: 4, trailing: 10))
.overlay(
// Add the outline
RoundedRectangle(cornerRadius: 8)
.stroke(Color.orange, lineWidth: 2))
// Second TextField
ZStack(alignment: .leading) {
if textFieldData.isEmpty {
Text("Email Address").italic()
www.bigmountainstudio.com 238
TextField
www.bigmountainstudio.com 239
TextField
Custom Composition
@State private var textFieldData = ""
...
VStack {
HStack {
Image(systemName: "magnifyingglass").foregroundColor(.gray)
TextField("first name", text: $textFieldData)
Image(systemName: "slider.horizontal.3")
}
Divider()
}
.padding()
HStack {
Image(systemName: "envelope")
.foregroundColor(.gray).font(.headline)
TextField("email address", text: $textFieldData)
}
.padding()
.overlay(RoundedRectangle(cornerRadius: 8).stroke(Color.gray, lineWidth: 1))
.padding()
HStack {
TextField("country", text: $textFieldData)
Button(action: {}) {
Image(systemName: "chevron.right").padding(.horizontal)
}
.accentColor(.orange)
}
.padding()
.overlay(Capsule().stroke(Color.gray, lineWidth: 1))
.padding()
www.bigmountainstudio.com 240
TextField
Keyboard Type
struct TextField_KeyboardType: View {
@State private var textFieldData = ""
Image(“KeyboardType")
Spacer()
}.font(.title)
}
}
www.bigmountainstudio.com 241
TextField
www.bigmountainstudio.com 242
TextField
.phonePad
www.bigmountainstudio.com 243
TextField
Spacer()
}.font(.title)
}
}
www.bigmountainstudio.com 244
TextField
Disable TextFields
struct TextField_Disabled: View {
@State private var lastName = "Moeykens"
@State private var city = "Salt Lake City"
@State private var disabled = false
Group {
TextField("Enter Last Name", text: $lastName)
TextField("Enter City", text: $city)
}
.disableAutocorrection(true)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding(.horizontal)
.disabled(disabled) // Don't allow to edit when disabled
.opacity(disabled ? 0.5 : 1) // Fade out when disabled
Spacer()
}.font(.title)
}
}
Note: The disabled modifier applies to ANY VIEW. Not just the TextField view.
www.bigmountainstudio.com 245
Toggle
The Toggle is a switch that can either be on or off. Much like other controls, you need to bind it to a variable. This variable is
passed into the Toggle’s initializer. Then, all you need to do is change this bound variable’s value to change the Toggle’s state
on or off. Or read the bound variable’s value to see what state the Toggle is currently in.
www.bigmountainstudio.com 246
Toggle
Introduction
@State private var isToggleOn = true
...
Text("The Toggle fills the width of its parent view.")
...
Toggle("Night Mode", isOn: $isToggleOn)
.padding()
There is not a lot you can do to change the colors of the thumb (round white circle), the on and off
positions. You can create your own custom Toggle. See the chapter on Custom Styling, in the section
ToggleStyle.
www.bigmountainstudio.com 247
OTHER VIEWS
Covered in the SwiftUI Views Mastery book.
Includes: Circle, Ellipse, Capsule, Rectangle, RoundedRectangle, Color, Divider, Group, Image, Path
and Inset along with the many modifiers and examples of how they work.
248
PAINTS
Covered in the SwiftUI Views Mastery book.
Includes: AngularGradient, ImagePaint, LinearGradient and RadialGradient with the many
examples of how they work when applied to different views.
SwiftUI 2 (iOS 14) content is locked in this preview. This is everything you get:
The complete SwiftUI Views Mastery book (PDF & ePub)
BONUS: The FULL Xcode Project ($997 Value)
BONUS: SwiftUI Views Study Guide ($97 Value)
BONUS: SwiftUI Views Flashcard Decks ($47 Value)
BONUS: My Personal Xcode Editor Theme ($17 Value)
SwiftUI 2 (iOS 14) content is locked in this preview. This is everything you get:
The complete SwiftUI Views Mastery book (PDF & ePub)
BONUS: The FULL Xcode Project ($997 Value)
BONUS: SwiftUI Views Study Guide ($97 Value)
BONUS: SwiftUI Views Flashcard Decks ($47 Value)
BONUS: My Personal Xcode Editor Theme ($17 Value)
SwiftUI 2 (iOS 14) content is locked in this preview. This is everything you get:
The complete SwiftUI Views Mastery book (PDF & ePub)
BONUS: The FULL Xcode Project ($997 Value)
BONUS: SwiftUI Views Study Guide ($97 Value)
BONUS: SwiftUI Views Flashcard Decks ($47 Value)
BONUS: My Personal Xcode Editor Theme ($17 Value)
SwiftUI 2 (iOS 14) content is locked in this preview. This is everything you get:
The complete SwiftUI Views Mastery book (PDF & ePub)
BONUS: The FULL Xcode Project ($997 Value)
BONUS: SwiftUI Views Study Guide ($97 Value)
BONUS: SwiftUI Views Flashcard Decks ($47 Value)
BONUS: My Personal Xcode Editor Theme ($17 Value)
SwiftUI 2 (iOS 14) content is locked in this preview. This is everything you get:
The complete SwiftUI Views Mastery book (PDF & ePub)
BONUS: The FULL Xcode Project ($997 Value)
BONUS: SwiftUI Views Study Guide ($97 Value)
BONUS: SwiftUI Views Flashcard Decks ($47 Value)
BONUS: My Personal Xcode Editor Theme ($17 Value)
SwiftUI 2 (iOS 14) content is locked in this preview. This is everything you get:
The complete SwiftUI Views Mastery book (PDF & ePub)
BONUS: The FULL Xcode Project ($997 Value)
BONUS: SwiftUI Views Study Guide ($97 Value)
BONUS: SwiftUI Views Flashcard Decks ($47 Value)
BONUS: My Personal Xcode Editor Theme ($17 Value)
GESTURES
Covered in the SwiftUI Views Mastery book.
Includes: Drag Gesture, On Long Press Gesture, Magnification Gesture, Rotation Gesture, On Tap
Gesture, Exclusive Gesture, Simultaneous Gesture, Sequence Gesture and High Priority Gesture
with the examples of how they work when applied to different views.
SwiftUI 2 (iOS 14) content is locked in this preview. This is everything you get:
The complete SwiftUI Views Mastery book (PDF & ePub)
BONUS: The FULL Xcode Project ($997 Value)
BONUS: SwiftUI Views Study Guide ($97 Value)
BONUS: SwiftUI Views Flashcard Decks ($47 Value)
BONUS: My Personal Xcode Editor Theme ($17 Value)
IMPORTING VIEWS
Covered in the SwiftUI Views Mastery book.
Includes how to use the new views that came with the release of iOS 14:
VideoPlayer view in the AVKit and Map view in the MapKit.
ACCESSIBILITY
Covered in the SwiftUI Views Mastery book.
Includes how to use the new views that came with the release of iOS 14:
VideoPlayer view in the AVKit and Map view in the MapKit.
THE END
I hope you enjoyed this free SwiftUI Views Quick Start!
This was just the beginning of a larger book.
More From Me
Over 900 pages of SwiftUI Find out how to implement action sheets, modals, popovers
Over 550 screenshots/videos showing you what you can do and custom popups
so you can quickly come back and reference the code Master all the layout modifiers including background and
Learn all the ways to work with and modify images overlay layers, scaling, offsets padding and positioning
See the many ways you can use color as views How do you hide the status bar in SwiftUI? Find out!
Discover the different gradients and how you can apply them This is just the tip of the mountain!
www.bigmountainstudio.com 259
Author
@BigMtnStudio
Patreon.com/bigmountainstudio Do you prefer hanging out in Instagram? Then follow and get bite-sized
My patrons get the first look at what I’m creating and when it comes chunks of dev info.
time to making a decision, they are my go-to people.
260
MORE FROM ME
I have some products (books and courses) you might also be interested in!
More From Me
Explorers Club
GET EXCLUSIVE ACCESS TO OVER $1,000 WORTH OF BOOKS AND COURSES
SwiftUI
262
More From Me
SwiftUI Animations
DO YOU LIKE ANIMATIONS?
WOULD YOU LIKE TO GET A FREE QUICK START GUIDE ON SWIFTUI ANIMATIONS WITH VIDEO AND CODE SAMPLES?
www.bigmountainstudio.com 263
More From Me
Uses simple language to describe complex things Learn tools in Xcode you probably don’t even know exist
Plenty of visuals so you understand more easily Visually see what automatic reference counting is and how it
Identify potential memory leak by the Swift type alone creates memory leaks
Remove confusions about Swift memory Learn the little known 2-Step method of fixing retain cycles
Find and fix memory leaks in real-world scenarios See example of how the Notification Center causes leaks
What’s the difference between strong, weak and unowned? Bonus section to help you conquer the interview!
www.bigmountainstudio.com 264
THANK YOU
I hope you have enjoyed this book as your visual quickstart reference guide. A lot of time and work went into this to make it as easy as possible for you to use.
If you find anything wrong or have suggestions for improvement, please let me know.
Found a way to create a cool UI? I’d be super interested to see it!
If you would like to write a positive review on how this book has helped you, I would love to hear that too! Also, indicate if your review is ok to publish. I may put your
review on social media, my website or in an email to others.
Email: [email protected]
More to Come
I’m constantly working on educational products so sign up to get notified with the latest news on my website www.bigmountainstudio.com.
www.bigmountainstudio.com 265
AFFILIATE INFO
An “affiliate” is someone who is associated with me and can earn money by promoting my products. I have an affiliate program that anyone can sign up for, whether
you bought the book or not. If you mention you like my book with your affiliate link and someone buys a book, you get:
20% !
If five people buy the book then your book is basically FREE. Beyond that, you have got yourself some extra spending money. 💰
www.bigmountainstudio.com 266
www.bigmountainstudio.com 267
SHARING TIPS
If you have never been an affiliate before and want some tips to effectively share my products then read on!
www.bigmountainstudio.com 268