SwiftUI View Modifiers Tutorial for iOS
Learn how to refactor your code to create powerful custom SwiftUI view modifiers. Make your views look consistent and your code easier to read and maintain. By Danijela Vrzan.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
SwiftUI View Modifiers Tutorial for iOS
20 mins
- Getting Started
- View Modifiers in SwiftUI
- Building a Title ViewModifier
- Creating a Text ViewModifier
- Extending the Text View
- Building a Button Style
- Creating a Button ViewModifier
- Refactoring ViewModifier Into a ButtonStyle
- Using the isPressed Property on Button Style
- Conditional ViewModifiers
- Creating a Conditional ViewModifier
- View Extensions With Default Parameters
- Creating an Image Modifier
- Ready for a Challenge?
- Where to Go From Here?
In SwiftUI, you can style your views using modifiers. You can use the built-in modifiers, but also create your own SwiftUI view modifiers. You’re probably already familiar with some of the built-in modifiers, like font()
to set a Text
view’s font attributes, frame()
to constrain the size of a view and padding()
to add whitespace around a view’s edges.
If you want to create your own SwiftUI view modifiers, there are two ways to do so. You can create a custom modifier by conforming to the ViewModifier
protocol or you can extend View
itself. The first approach has one advantage — you’re able to define custom stored properties.
In this tutorial, you’ll use an app called AdoptAPet, a simple master-detail view app, meaning there is a master view that shows high-level information, in this case an adoptable furry friend’s picture and name, and then a detail view that displays when the user taps a list row.
You’ll refactor AdoptAPet as you learn how to use SwiftUI’s ViewModifier
protocol for:
- Creating custom view modifiers.
- Building new button styles.
- Creating modifiers with conditional parameters.
- Extending views to create reusable components.
Getting Started
Download the starter project by clicking Download Materials at the top or bottom of the tutorial.
Open AdoptAPet.xcodeproj inside the starter folder. Build and run to see the app in action:
AdoptAPet is a simple app with a list of available animals and a detailed view displaying more information about the selected dog or cat.
Views in the app have a lot of styling modifiers, some of which repeat multiple times. This makes your code harder to read and maintain.
You’ll learn how to create custom SwiftUI view modifiers to make your views easier to read. But before that, take a moment to learn about SwiftUI view modifiers in general.
View Modifiers in SwiftUI
View modifiers are methods you call on your views to customize their appearance and behavior. Views and modifiers work together to define your UI.
You can use view modifiers to:
- Add accessibility features.
- Customize the design by applying styling such as colors, fonts and more.
- Add actions and respond to events.
- Configure other components, like toolbars and navigation bars.
- Present other views, like sheets and alerts.
You can modify any type that conforms to View
. This includes Text
, Button
, Image
and any custom View
you create.
The result of a SwiftUI view modifier is a View
. This lets you chain multiple modifiers, listing them immediately one after another, to create another view.
SwiftUI comes with a set of predefined standard modifiers that you can use to design your UI. For example, when you want to add color to a Text
view, you can apply the .foregroundColor()
modifier.
You are also able to create your own custom modifiers using the ViewModifier
protocol. The most common use case for creating custom view modifiers is bundling a set of modifiers you plan to reuse multiple places in your code.
Consider creating a button style and then using it across your app:
You have to repeat your code in multiple places.
Creating your own modifier for a single component that you’ll reuse keeps your code DRY (Don’t Repeat Yourself):
It makes it easier to edit the code and gives you a single source of truth. It’s a small change that can make a big difference. Just imagine, the next time designers decide to switch from twenty-point padding down to 18, you won’t have to chase down this change multiple places in your code. It’ll be right there in one neat, easy-to-update place.
Read on to learn how to make this magic time-saving happen by building your own view modifiers.
Building a Title ViewModifier
You don’t think about optimizing your code while writing it. First, you make it work. Then, you do some refactoring.
When styling UI components, look for the lines of code where you repeat modifiers multiple times in different files.
In Xcode, open PetDetailedInformationView.swift and take a look at each of the top-level Text
views inside the VStack
:
Every title in the stack has identical styling and a repeated set of modifiers.
There are different approaches you could take here to avoid that repetition.
Every Text
and HStack
pair are identical. The only differences are each title’s text and the SFSymbol icon and detail property that follow it. You could extract the Text
and HStack
to a separate view and provide these values, but you still need to call it five times with different parameters.
Instead, you’ll create a view modifier.
Creating a Text ViewModifier
There’s a folder in your project called ViewModifiers and a file with the same name. You’ll create all your modifiers in this file to keep them handy in one place.
Keeping all custom modifiers in a single file makes them easier to maintain and change when needed. Think of it as creating an application-wide style guide. Anyone can refer to this view modifier file if they need to create a UI component that matches the defined app style or if they want to see how a particular look was achieved.
Open ViewModifiers.swift and replace // TODO: 1
with:
// 1
struct DetailedInfoTitleModifier: ViewModifier {
// 2
func body(content: Content) -> some View {
content
// 3
.lineLimit(1)
.font(.title2)
.bold()
}
}
Here’s what’s happening:
- You create a struct called
DetailedInfoTitleModifier
that conforms to theViewModifier
protocol. It’s a good idea to provide a descriptive name, especially when you start creating more modifiers. - To conform to
ViewModifier
, you need to add thebody(content:)
method that returnssome View
. Thecontent
parameter is the view on which you apply the modifiers. - Finally, you add all your modifiers.
Now, go back to PetDetailedInformationView.swift and replace the three modifiers below Text("Breed")
with:
.modifier(DetailedInfoTitleModifier())
Build and run the app. Select a pet, and you’ll see nothing has changed:
That’s precisely the outcome you want, and everything looks exactly as intended. You haven’t changed the styling; you’ve only moved the modifiers to a different file.
Now, apply that same modifier to the rest of the titles by replacing existing modifiers below Text("Characteristics")
, Text("Size")
, Text("Sex")
and Text("Age")
.
Notice how you need to call .modifier(DetailedInfoTitleModifier())
every time you want to apply your modifier. It looks redundant.
To avoid that, you’ll extend the Text
to make your modifier accessible in a more convenient way.