The easiest way to display text in SwiftUI is to use Text
view initializer that accepts a string literal, like in the example below.
Text("Hello World!")
When we create Text
with a string literal, the initializer that is actually called is the one that accepts a LocalizedStringKey
: init (_: tableName: bundle: comment 🙂. This happens because LocalizedStringKey
conforms to ExpressibleByStringLiteral protocol.
SwiftUI assumes that if we have a static string inside a text view, we’ll likely want to localize it. SwiftUI performs a search for localizations on our behalf and falls back to displaying the key (the string literal that we passed to the initializer), if no localizations were found.
LocalizedStringKey
can also be created from a string interpolation, like in the following example.
Text("Your next appointment is on (appointmentDate).")
This functionality allows us to insert variables, images, formatted dates and even display rich text with an AttributedString
or text modifiers.
In this article we will explore what is possible to achieve by leveraging string interpolation in LocalizedStringKey
and how to avoid common pitfalls.
Supported types for LocalizedStringKey interpolation
To know what types we can interpolate inside LocalizedStringKey
we can check different appendInterpolation()
methods it supports in documentation for LocalizedStringKey.StringInterpolation. We never call these methods manually, the compiler calls them for us when we create a LocalizedStringKey
with interpolation.
Notice that if we try to interpolate something that is not supported, we will get a compile-time error. For example, if we try to insert a Button
inside a LocalizedStringKey
the error will say: Instance method 'appendInterpolation' requires that 'Button<Text>' conform to '_FormatSpecifiable'
.
There are many different types that can be interpolated inside a LocalizedStringKey
here I would like to go over some of the most interesting use cases.
Images
LocalizedStringKey
interpolation supports appending Image
views. We can interpolate symbol images or regular images.
Text("Delete item (Image(systemName: "trash"))")
Text("Completed task (Image("checkmark"))")
Formatted data
We can interpolate data formatted using FormatStylesuch as dates, lists, numbers, measurements and more.
Text("Today is (Date(), format: .dateTime.month().day()).")
let listOfFriends = ["Peter", "Jane", "Max", "Kate"]
Text("You should invite (listOfFriends, format: .list(type: .and)).")
let remainingDistance = Measurement<UnitLength>(value: 20, unit: .miles)
Text("""
The remaining distance is (
remainingDistance,
format: .measurement(width: .wide, usage: .road)
).
""")
AttributedString
To display rich text, we can use an AttributedString. SwiftUI does not support all the attributes supported by UIKit and AppKit at the moment, but there are still some useful styles that we can set. For the list of supported attributes in SwiftUI we can check AttributeScopes.SwiftUIAttributes. The attributes that are not included in SwiftUI scope will be ignored by the text view.
For example, to add a background color to a portion of text, we can create an attributed string for that portion and add backgroundColor
attribute. Then we can interpolate that string inside a LocalizedStringKey
.
struct ContentView: View
var date: AttributedString
var result = AttributedString(
Date().formatted(.dateTime.month().day())
)
result.backgroundColor = .blue
return result
var body: some View
Text("Today is (date).")
Text
Another way to display rich text is to interpolate Text
with some modifiers inside another Text
. We have to make sure that we use modifiers that return Text
and not some View
. We can find the list of text modifiers in Text view documentation in the “Styling the View’s Text” section.
Text("""
You should arrive at least (Text("30 min").bold()) in advance.
""")
Text interpolation as shown in the example above is usually preferred over text concatenation where we use +
sign to combine text views. Text interpolation can be more efficient and has better support for localization, since the order of the words can vary in different languages.
LocalizedStringKey interpolation vs DefaultStringInterpolation
I would like to point out that string interpolation inside LocalizedStringKey
does not have the same functionality as string interpolation inside a regular Swift String
.
For the list of types that we can interpolate inside LocalizedStringKey
we can check appendInterpolation()
methods in LocalizedStringKey.StringInterpolation documentation. We can compare them to appendInterpolation()
methods for regular strings in documentation for DefaultStringInterpolation.
Even if we can interpolate the same type inside a LocalizedStringKey
and a String
, the result might not always be the same. As an example, we can compare what we get by interpolating an Image
view inside a String
versus inside a LocalizedStringKey
.
If we want to save the string with interpolated image in a variable and pass it to our text view, then we need to be careful. If we do not indicate the variable type, it will be treated as a regular string and will be initialized with DefaultStringInterpolation
instead of LocalizedStringKey.StringInterpolation
.
struct ContentView: View
let textString = "Delete item (Image(systemName: "trash"))"
var body: some View
Text(textString)
The result of passing a string variable with interpolated image to SwiftUI Text
view can be surprising. We can see that instead of the SF symbol Text is displaying the image description. This is how DefaultStringInterpolation
for regular strings works.
To correct this issue, we need to indicate that we are creating a LocalizedStringKey
not a regular string.
struct ContentView: View
let textString: LocalizedStringKey = "Delete item (Image(systemName: "trash"))"
var body: some View
Text(textString)
As expected, SwiftUI will display a text view with an SF Symbol inside.

For updates about the blog and development tips follow us on Twitter @nilcoalescing.