Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
8 views

Lec05 SwiftUI Tips and Tricks - A Free SwiftUI by Example Tutorial

The document provides a comprehensive guide on SwiftUI tips and tricks, aimed at helping developers enhance their app development experience. It covers various topics such as using state properties, creating constant bindings for prototyping, presenting test views, and utilizing semantic colors and adaptive padding. Additionally, it includes advice on customizing modifiers, animating changes, and improving previewing capabilities in Xcode, making it a valuable resource for SwiftUI developers.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views

Lec05 SwiftUI Tips and Tricks - A Free SwiftUI by Example Tutorial

The document provides a comprehensive guide on SwiftUI tips and tricks, aimed at helping developers enhance their app development experience. It covers various topics such as using state properties, creating constant bindings for prototyping, presenting test views, and utilizing semantic colors and adaptive padding. Additionally, it includes advice on customizing modifiers, animating changes, and improving previewing capabilities in Xcode, making it a valuable resource for SwiftUI developers.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 10

2/1/2021 SwiftUI tips and tricks - a free SwiftUI by Example tutorial

NEW: Start my new Ultimate Portfolio App course with a free Hacking with Swift+ trial! >>

< How to use Instruments to profile Understanding property wrappers in


your SwiftUI code and identify slow Swift and SwiftUI >
layouts

SwiftUI tips and tricks


Paul Hudson  @twostraws October 20th 2019
Updated for Xcode 12.0
SwiftUI is packed with powerful headline features, but there are also dozens of smaller tips
and tricks that will help you write better apps.
Iʼve tried to summarize all the tips Iʼve come across so far below, and where applicable Iʼve
also provided links to my more in-depth SwiftUI tutorials to help give you extra context.

Resume the live preview


Having a live preview of your layouts while you code is a great feature of Xcode, but often
youʼll see it pause because you changed a lot and Xcode couldnʼt keep up.
Rather than constantly reaching for your trackpad to press Resume, hereʼs the most
important keyboard shortcut for SwiftUI developers: press Option-Cmd-P to make the
preview window reload immediately, and resume its live updates.

Make @State private


Apple provides us with three ways to use state in our apps: is for simple local
@State
properties, @ObservedObject is for complex properties or properties that are shared
between views, and @EnvironmentObject is for properties that are indirectly shared
potentially by many views.
Because @State is specifically designed for use by the local view, Apple recommends
marking @State properties as private to really re-enforce that they arenʼt designed to
be accessed elsewhere:
@State private var score = 0

Read more: Whatʼs the difference between @ObservedObject, @State, and


@EnvironmentObject?

Prototype with constant bindings


If youʼre just trying out a design and donʼt want to have to create bindings to use things like
text fields and sliders, you can use a constant binding instead. This will allow you to use the
object with a realistic value.
For example, this creates a text field with the constant string “Hello”:

https://www.hackingwithswift.com/quick-start/swiftui/swiftui-tips-and-tricks 1/10
2/1/2021 SwiftUI tips and tricks - a free SwiftUI by Example tutorial

TextField("Example placeholder", text: .constant("Hello"))


.textFieldStyle(RoundedBorderTextFieldStyle())
NEW: Start my new Ultimate Portfolio App course with a free Hacking with Swift+ trial! >>
And this creates a slider with a constant value of 0.5:
Slider(value: .constant(0.5))

Note: Constant bindings like this one are just for testing and illustration purposes – you
canʼt change them at runtime.

Presenting test views


Another useful tip while youʼre prototyping is that you can present any kind of view rather
than a full detail view – even when working with a navigation view.
For example, if you had a list of users and wanted to make sure that tapping one of them
worked, you could use a navigation link that points to a text view rather than a fully fledged
custom custom view, like this:
struct ContentView: View {
let users = (1...100).map { number in "User \(number)" }

var body: some View {


NavigationView {
List(users, id: \.self) { user in
NavigationLink(destination: Text("Detail for \(u
Text(user)
}
}.navigationBarTitle("Select a user")
}
}
}

This allows you to make one screen complete before going on to design the real detail
view.
Read more: How to push a new view onto a NavigationView.

Go past the 10 view limit


All containers in SwiftUI must return no more than ten children, which is usually fine for
most purposes. However, if you need to have more than 10 views, if you need to return
more than one view from your body property, or if you need to return several different
kinds of view, you should use a group like this:

https://www.hackingwithswift.com/quick-start/swiftui/swiftui-tips-and-tricks 2/10
2/1/2021 SwiftUI tips and tricks - a free SwiftUI by Example tutorial

struct ContentView: View {


var body: some View {
NEW: Start my new Ultimate Portfolio App course with a free Hacking with Swift+ trial! >>
List {
Group {
Text("Row 1")
Text("Row 2")
Text("Row 3")
Text("Row 4")
Text("Row 5")
Text("Row 6")
}

Group {
Text("Row 7")
Text("Row 8")
Text("Row 9")
Text("Row 10")
Text("Row 11")
}
}
}
}

Groups are purely logical containers – they donʼt affect your layouts.
Read more: How to group views together.

Use semantic colors


SwiftUI is designed to work with themed user interfaces out of the box, which means it
provides both semantic and adaptive colors by default. Although it might be tempting to
use your own custom colors, you should at least check first whether you have something in
the default SwiftUI set.
For example, Color.red isnʼt the pure red of RGB(255, 0, 0), but instead slightly lighter or
slightly darker based on the environment – it adapts automatically without us needing to
think about it.
Similarly, Color.primary, Color.secondary, and Color.accentColor all refer to
fixed values that are provided by the environment, allowing us to structure and highlight
content in a standardized way.
Read more: How to style text views with fonts, colors, line spacing, and more.

Rely on adaptive padding


SwiftUI lets us control precisely how much padding to apply around views, like this:
Text("Row 1")
.padding(10)

While itʼs tempting to always control padding like this to “get things just right”, if you use
the padding() modifier without any parameters you get adaptive padding – padding that
automatically adjusts itself to its content and its environment.
https://www.hackingwithswift.com/quick-start/swiftui/swiftui-tips-and-tricks 3/10
2/1/2021 SwiftUI tips and tricks - a free SwiftUI by Example tutorial

So, if your app is running on an iPad with a regular size class youʼll get more padding than if
the user moves it down to a split view – all without having to write any code.
NEW:HowStart
Read more: my newspacing
to control Ultimate Portfolio
around Appviews
individual courseusing
withpadding.
a free Hacking with Swift+ trial! >>

Combine text views


You can create new text views out of several small ones using , which is an easy way of +
creating more advanced formatting. For example, this creates three text views in different
colors and combines them together:
struct ContentView: View {
var body: some View {
Text("Colored ")
.foregroundColor(.red)
+
Text("SwifUI ")
.foregroundColor(.green)
+
Text("Text")
.foregroundColor(.blue)
}
}

Read more: How to combine text views together.

How to make print() work


If you press play in the SwiftUI preview to try out your designs, youʼll find that any calls to
print() are ignored. If youʼre using print() for testing purposes – e.g. as simple button
tap actions – then this can be a real headache.
Fortunately, thereʼs a simple fix: right-click on the play button in the preview canvas and
choose “Debug Preview”. With that small change made youʼll find your print() calls work
as normal.

Relying on the implicit HStack


When you create a list of items, itʼs common to want to get the iOS-standard look of having
an image on the left then some text on the right.
Well, if youʼre using a dynamic list of items – i.e., a list thatʼs attached to an array of data –
then you actually get a HStack for free inside your list, so thereʼs no need to make one by
hand.
So, this code will create a list based on picture names from an array, and relies on the
implicit HStack to arrange the image and text side by side:

https://www.hackingwithswift.com/quick-start/swiftui/swiftui-tips-and-tricks 4/10
2/1/2021 SwiftUI tips and tricks - a free SwiftUI by Example tutorial

struct ContentView: View {


let imageNames = ["paul-hudson", "swiftui"]
NEW: Start my new Ultimate Portfolio App course with a free Hacking with Swift+ trial! >>
var body: some View {
List(imageNames, id: \.self) { image in
Image(image).resizable().frame(width: 40)
Text(image)
}
}
}

Read more: How to use implicit stacking.

Splitting up large views


If you find yourself with a large view you might find it easier to break it up into several
smaller views and compose those together to get the same result. One of the great
features of SwiftUI is that thereʼs no performance difference because it flattens its view
hierarchy, but it certainly makes maintenance easier!
For example, hereʼs a list that shows an image, a title, and a subtitle for every users:
struct ContentView: View {
let users = ["Paul Hudson", "Taylor Swift"]

var body: some View {


NavigationView {
List(users, id: \.self) { user in
NavigationLink(destination: Text("Detail View"))
Image("example-image").resizable().frame(wid

VStack(alignment: .leading) {
Text("Johnny Appleseed").font(.headline)
Text("Occupation: Programmer")
}
}
}.navigationBarTitle("Users")
}
}
}

Even though itʼs not really that complicated, you still need to read it carefully to understand
what itʼs going on.
Fortunately, we can take parts of the view out into a separate view to make it easier to
understand and easier to re-use, and Xcode makes it a cinch: just Cmd-click on the
navigation link and choose Extract Subview. This will pull the code out into a new SwiftUI
view, and leave a reference where it was.
Note: If your subview relies on data from the parent youʼll need to pass that along yourself.
Read more: How to create and compose custom views.

https://www.hackingwithswift.com/quick-start/swiftui/swiftui-tips-and-tricks 5/10
2/1/2021 SwiftUI tips and tricks - a free SwiftUI by Example tutorial

Better previewing
NEW:benefits
One of the many Start my new Ultimate
of SwiftUI is that wePortfolio Apppreviews
get instant course with
of oura layouts
free Hacking
as we with Swift+ trial! >>
work. Even better, we can customize those previews so that we can see multiple designs
side by side, see how things look with a navigation view, try out dark mode, and more.
For example, this creates a preview for ContentView that shows three different designs
side by side: extra large text, dark mode, and a navigation view:
#if DEBUG
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
Group {
ContentView()
.environment(\.sizeCategory, .accessibilityExtra
ContentView()
.environment(\.colorScheme, .dark)
NavigationView {
ContentView()
}
}
}
}
#endif

Tip: Make sure you zoom out or scroll around in the preview window to see all the different
previews.
Read more: How to preview your layout in different devices.

Create custom modifiers


If you find yourself regularly repeating the same set of view modifiers – for example,
making a text view have padding, be of a specific size, have fixed background and
foreground colors, etc – then you should consider moving those to a custom modifier
rather than repeating your code.
For example, this creates a new PrimaryLabel modifier that adds padding, a black
background, white text, a large font, and some corner rounding:
struct PrimaryLabel: ViewModifier {
func body(content: Content) -> some View {
content
.padding()
.background(Color.black)
.foregroundColor(.white)
.font(.largeTitle)
.cornerRadius(10)
}
}

You can now attach that to any view using .modifier(PrimaryLabel()), like this:

https://www.hackingwithswift.com/quick-start/swiftui/swiftui-tips-and-tricks 6/10
2/1/2021 SwiftUI tips and tricks - a free SwiftUI by Example tutorial

struct ContentView: View {


var body: some View {
NEW: Start my new Ultimate Portfolio App course with a free Hacking with Swift+ trial! >>
Text("Hello World")
.modifier(PrimaryLabel())
}
}

Read more: How to create custom modifiers.

Animate changes easily


SwiftUI has two ways for us to animate changes to its view hierarchy: animation() and
withAnimation() . They are used in different places, but both have the effect of
smoothing out changes to the views in our app.
The animation() method is used on bindings, and it asks SwiftUI to animate any
changes that result in the bindingʼs value being modified. For example, hereʼs a view that
has a Toggle to show or hide a label:
struct ContentView: View {
@State private var showingWelcome = false

var body: some View {


VStack {
Toggle(isOn: $showingWelcome) {
Text("Toggle label")
}

if showingWelcome {
Text("Hello World")
}
}
}
}

When the toggle is changed, the text view below it will appear or disappear immediately,
which isnʼt a great experience. However, if we used animation() we could make the view
slide in and out smoothly when the toggle is changed:
Toggle(isOn: $showingWelcome.animation()) {
Text("Toggle label")
}

You can even control the kind of animation you want, like this:
Toggle(isOn: $showingWelcome.animation(.spring())) {
Text("Toggle label")
}

When youʼre working with regular state rather than bindings, you can animate changes by
wrapping them in a withAnimation() call.
https://www.hackingwithswift.com/quick-start/swiftui/swiftui-tips-and-tricks 7/10
2/1/2021 SwiftUI tips and tricks - a free SwiftUI by Example tutorial

For example, hereʼs our same view except now it shows or hide the welcome label using a
button press:
NEW: Start my new Ultimate Portfolio App course with a free Hacking with Swift+ trial! >>
struct ContentView: View {
@State private var showingWelcome = false

var body: some View {


VStack {
Button(action: {
self.showingWelcome.toggle()
}) {
Text("Toggle label")
}

if showingWelcome {
Text("Hello World")
}
}
}
}

As with before that will cause the welcome label to appear and disappear immediately, but
if we wrap our changes in withAnimation() they will be animated instead:
withAnimation {
self.showingWelcome.toggle()
}

And itʼs customizable in exactly the same way as animation():


withAnimation(.spring()) {
self.showingWelcome.toggle()
}

Read more: How to add and remove views with a transition.

Showing multiple
If you try to attach multiple
alerts in a view
modifiers to a single view, youʼll find your code
alert()
doesnʼt work as you expect – one alert will work but the other wonʼt.
To fix this, you should attach your alerts to different parts of your view hierarchy, such as to
the button or other view that triggers the alert to appear.
Read more: How to show multiple alerts in a single view.

Publishing new values from a binding


Last but not least, to avoid problems when sending update notifications from a publisher –
e.g. calling send() on a PassthroughSubject or updating any @Published property –
you should make sure youʼre always on the main thread.

https://www.hackingwithswift.com/quick-start/swiftui/swiftui-tips-and-tricks 8/10
2/1/2021 SwiftUI tips and tricks - a free SwiftUI by Example tutorial

As with UIKit and most other UI frameworks, you can do all the background work you want
in your SwiftUI apps, but you should only ever manipulate the user interface on the main
thread. Because stateStart
changes automatically trigger aApp
refresh of your body, itʼs important
that you make sure you perform those state changes on the main thread.a free Hacking with Swift+ trial! >>
NEW: my new Ultimate Portfolio course with
Read more: How to use @ObservedObject to manage state from external objects.

What are your tips?


The SwiftUI tips and tricks above are ones Iʼve come across watching WWDC sessions,
asking questions in the labs, and writing lots and lots of code while moving my own
projects from UIKit.
Iʼd love to hear what tips you have – send me a tweet @twostraws and let me know!

SPONSORED Are you tired of wasting time debugging your Swift app? Instabugʼs SDK
is here to help you minimize debugging time by providing you with complete device
details, network logs, and reproduction steps with every bug report. All data is
attached automatically. It only takes a line of code to setup. Start your free trial now
and ship quality apps!
Try it for free

Sponsor Hacking with Swift and reach the world's largest Swift community!

Similar solutions…
All SwiftUI property wrappers explained and compared
How to use Instruments to profile your SwiftUI code and identify slow layouts
Answering the big question: should you learn SwiftUI, UIKit, or both?
Building a menu using List
Frequently asked questions about SwiftUI

< How to use Instruments to profile Understanding property wrappers in


your SwiftUI code and identify slow Swift and SwiftUI >
layouts

Was this page useful? Let us know!


☆☆☆☆☆
Average rating: 4.7/5

https://www.hackingwithswift.com/quick-start/swiftui/swiftui-tips-and-tricks 9/10
2/1/2021 SwiftUI tips and tricks - a free SwiftUI by Example tutorial

NEW: Start myClnew


ickUltimate
here toPortfolio
visit theAppHacki
coursengwith
witahfreeSwiHacking
ft storewith>>Swift+ trial! >>


@twostraws

paul@hackingwithswift.com

Sponsor the site
About Glossary Privacy Policy Refund Policy Update Policy Code of Conduct
Thanks for your support, Herman C Vermeulen!

Swift, the Swift logo, Swift Playgrounds, Xcode, Instruments, Cocoa Touch, Touch ID, AirDrop, iBeacon, iPhone, iPad, Safari, App Store,
watchOS, tvOS, Mac and macOS are trademarks of Apple Inc., registered in the U.S. and other countries. Pulp Fiction is copyright © 1994
Miramax Films. Hacking with Swift is ©2021 Hudson Heavy Industries.

You are not logged in


Log in or create account

https://www.hackingwithswift.com/quick-start/swiftui/swiftui-tips-and-tricks 10/10

You might also like