Text > TextBuilder
Like a SwiftUI ViewBuilder, but for Text.
TextBuilder
Introduction
Text composition in SwiftUI can often be cumbersome, especially when there's logic affecting its format and content.
TextBuilder leverages the power of Swift Macros to solve this problem. The @TextBuilder macro transforms functions into builder-style closures, making text composition intuitive and readable.
Installation
Add TextBuilder to your Swift Package Manager dependencies:
.package(url: "https://github.com/davdroman/swiftui-text-builder", from: "4.0.0"),
Then, add the dependency to your desired target:
.product(name: "TextBuilder", package: "swiftui-text-builder"),
Usage
Basic Usage
Apply @TextBuilder to functions that return Text. The macro will transform the function body into a builder-style closure that concatenates text segments.
@TextBuilder
func loremIpsum() -> Text {
Text("Lorem").underline().foregroundColor(.blue)
Text("ipsum dolor")
Text("sit").bold()
Text("amet, consectetur")
}
This creates a concatenated Text without any separators between segments.
With Separators
You can specify a separator to be inserted between text segments:
@TextBuilder(separator: " ")
func spacedText() -> Text {
Text("Lorem").underline().foregroundColor(.blue)
Text("ipsum dolor")
Text("sit").bold()
Text("amet, consectetur")
}
For multiline text:
@TextBuilder(separator: "\n")
func multilineText() -> Text {
Text("Lorem").underline().foregroundColor(.blue)
Text("ipsum dolor")
Text("sit").bold()
Text("amet, consectetur")
}
String Support ✨
TextBuilder accepts String types directly and provides a convenient .text computed property:
@TextBuilder(separator: " ")
func mixedText() -> Text {
"Hello" // String literal becomes verbatim Text
"world".text.bold() // Use .text for chaining modifiers
String(2025) // Any StringProtocol works
}
Control Flow
TextBuilder supports Swift's control flow statements:
@TextBuilder(separator: " ")
func conditionalText(showDetails: Bool) -> Text {
"Hello"
if showDetails {
"with details"
} else {
"basic"
}
if let name = userName {
name.text.italic()
}
for i in 1...3 {
String(i)
}
}
Alternative API
If you prefer not to use macros, you can use the underlying Text initializer directly:
var body: some View {
Text(separator: " 👏 ") {
"Lorem".text.underline().foregroundColor(.blue)
"ipsum dolor"
"sit".text.bold()
"amet, consectetur"
}
}
This is useful if you simply want to insert some rich text into a view body without defining a separate function.
Limitations
The @TextBuilder macro currently cannot be applied to computed properties due to Swift limitations. Use functions instead.
See Swift Issue #75715 for updates on computed property support.