Text modifiers in SwiftUI
Apart from regular view modifiers in SwiftUI, there are also text modifiers. They apply specific styles to a Text
view and return another Text
rather than some View
. We can see the list of available text modifiers in the Text view documentation under the "Styling the view’s text" and other sections. These are the ones that have Text
as their return type, for example func bold(_ isActive: Bool) -> Text
.
# Text modifiers use cases
Text modifiers are great for styling portions of text and can be used inside text interpolation.
To emphasize certain words in a sentence, we can interpolate text with the bold() modifier applied.
Text("The market days are \(Text("Wednesday").bold()) and \(Text("Sunday").bold()).")
We can also use text modifiers to apply specific styles to links inside Text
views, for example add an underline.
Text("For more information visit our \(Text("[website](https://example.com)").underline()).")
Note, that foregroundStyle()
modifier won't work in this case. To change the color of links, we should apply tint() on the entire text view, or interpolate an AttributedString with a foregroundColor
attribute. Link color is only customizable on iOS. For more tips about styling links, check out my previous post Customize the style of links embedded in Text.
As well as with text interpolation, text modifiers can be used to style portions of text combined by text concatenation.
Text(verbatim: "Nil Coalescing").foregroundStyle(.purple) + Text(verbatim: " Limited")
We should always prefer text interpolation versus text concatenation for localizable text, because it supports a flexible order of words in a sentence. But it's fine to combine Text views with a plus sign when it's not going to be localized, if we find it more convenient.
If we accidentally use a view modifier instead of a text modifier with text interpolation or text concatenation, we will get a build error. When we try to apply textCase()
instead of foregroundStyle()
to the example above, Xcode says Cannot convert value of type 'some View' to expected argument type 'Text'
.
// Error: Cannot convert value of type 'some View' to expected argument type 'Text'
Text(verbatim: "Nil Coalescing").textCase(.uppercase) + Text(verbatim: " Limited")
This happens because textCase() returns some View
and not Text
.
# Combining multiple modifiers in one
If we want to combine multiple text modifiers in one to make our code more readable or to more easily reuse it in different places, we can extend Text
with a function that has Text
as its return type.
For example, if we need to make some parts of the text italic and bold at the same time, we can define boldItalic()
method on Text
view.
extension Text {
func boldItalic() -> Text {
self.bold().italic()
}
}
We can then use that newly defined text modifier anywhere we can use the standard framework ones.
Text("The party is \(Text("tomorrow").boldItalic())")