Displaying Markdown in SwiftUI: A Step-by-Step Tutorial
Since the release of SwiftUI for iOS 15, SwiftUI has had a built-in feature for displaying Markdown text using the Text widget. While not all Markdown formats are supported yet, it's sufficient if you only want to display text in some formats or perhaps embed links.
To write Markdown within SwiftUI, you simply use the Text widget and write Markdown within that Text.
struct ContentView: View {
var body: some View {
VStack {
Text("This is just regular Text")
Text("This with **Bold** style")
Text("This with *Italic* style")
Text("This one with ~Strikethrough~ style")
Text("This one with `Monopace`")
Text("This one with [Goto Google](www.google.com) Link")
}
.padding()
}
}
#Writing Markdown in a Variable
If you want to display Markdown using a variable, you will most likely use the following code.
struct ContentView: View {
@State private var text: String = "**SwiftUI** helps you build great-looking apps across all _Apple_ platforms with the power of Swift — and surprisingly little code. You can bring even better experiences to everyone, on any Apple device, using just one set of tools and APIs.[SwiftUI](https://developer.apple.com/xcode/swiftui/)"
var body: some View {
VStack {
Text(text)
}
.padding()
}
}
Unfortunately, this approach won't work. Instead of displaying Markdown, it will only display the text as regular text.
This is because if you write Markdown text directly into the Text widget, SwiftUI will automatically convert that text into a LocalizedStringKey. On the other hand, if the text is stored in a variable with String data type, than Text widget will not consider it as a LocalizedStringKey but rather as a regular String.
Therefore, if you want to write Markdown text into a variable, make sure to change the variable type to LocalizedStringKey or convert the String into a LocalizedStringKey first.
struct ContentView: View {
@State private var text: String = "**SwiftUI** helps you build great-looking apps across all _Apple_ platforms with the power of Swift — and surprisingly little code. You can bring even better experiences to everyone, on any Apple device, using just one set of tools and APIs.[SwiftUI](https://developer.apple.com/xcode/swiftui/)"
// declare variable as LocalizeStringKey instead
@State private var localizeText: LocalizedStringKey = "**SwiftUI** helps you build great-looking apps across all _Apple_ platforms with the power of Swift — and surprisingly little code. You can bring even better experiences to everyone, on any Apple device, using just one set of tools and APIs.[SwiftUI](https://developer.apple.com/xcode/swiftui/)"
var body: some View {
VStack {
// convert String to LocalizedStringKey first
Text(LocalizedStringKey(text))
Divider()
Text(localizeText)
}
.padding()
}
}
#Changing Link Color
By default, if you write a link in Markdown, SwiftUI will automatically render the link with the default Button text color, which is usually blue. If you want to change this color, you can add the .tint
modifier to the Text widget.
struct ContentView: View {
var body: some View {
VStack {
Text("Regular [link](https://apple.com) with default color")
Text("Styled [link](https://apple.com) with custom color [hyperlink](https://apple.com)")
.tint(.pink)
}
.padding()
}
}
#Working with AttributedString
What is AttributedString ? An AttributedString is a value type for a string with associated attributes for portions of its text.
@dynamicMemberLookupstruct AttributedString
By using AttributedString, you can format specific parts of the text, such as with specific colors, sizes, and fonts. By combining the built-in Markdown feature, you can create Text displays with various formats, as shown in the example below.
struct ContentView: View {
private var attrText: AttributedString {
do {
var text = try AttributedString(
markdown: "**SwiftUI** helps you build great-looking apps across all _[Apple](https://apple.com)_ platforms with the power of Swift — and surprisingly little code. You can bring even better experiences to everyone, on any ~Apple device~, using just one set of tools and APIs."
)
if let range = text.range(of: "SwiftUI") {
text[range].backgroundColor = .yellow
text[range].foregroundColor = .red
}
if let range = text.range(of: "Apple") {
text[range].foregroundColor = .purple
text[range].font = .system(size: 30)
}
if let range = text.range(of: "Apple device") {
text[range].backgroundColor = .red
text[range].foregroundColor = .white
text[range].font = .boldSystemFont(ofSize: 25)
}
return text
} catch {
return "Error text attribute"
}
}
var body: some View {
VStack {
Text(attrText)
}
.padding()
}
}
#Markdown limitation in SwiftUI
As of the time of writing, SwiftUI does not yet support all Markdown syntax. Some of these unsupported elements include: images, numbered lists, and headings.