Displaying Markdown in SwiftUI: A Step-by-Step Tutorial

This article contains tips on how to easily display Markdown in SwiftUI using the Text widget, as well as how to change link colors and use AttributedString

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()
    }
}
Easy Way to Display Markdown in  SwiftUI using Text
Writing markdown in Text

#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.

Easy Way to Display Markdown in  SwiftUI using 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()
    }
}
Easy Way to Display Markdown in  SwiftUI using Text

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()
    }
}
Easy Way to Display Markdown in  SwiftUI using Text

#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()
    }
}
Easy Way to Display Markdown in  SwiftUI using Text

#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.

GitHub - meshwara/SwiftUI-Markdown-Sample
Contribute to meshwara/SwiftUI-Markdown-Sample development by creating an account on GitHub.