```html SwiftUI: How to Implement Syntax Highlighting (iOS 17+, 2026)

How to implement syntax highlighting in SwiftUI

iOS 17+ Xcode 16+ Advanced APIs: AttributedString / Regex Updated: 2026-05-12

TL;DR

Build a AttributedString from your code string, iterate over Swift Regex matches for each token type, tint each run's foregroundColor, then render the whole thing with a plain Text view.

var result = AttributedString(code)
let keywords = #/\b(func|var|let|struct|class|enum|if|else|return|guard|import)\b/#
for match in code.matches(of: keywords) {
    if let r = Range(match.range, in: result) {
        result[r].foregroundColor = .purple
    }
}
// Render:
Text(result).font(.system(.body, design: .monospaced))

Full implementation

import SwiftUI

// MARK: – Highlighter

struct SyntaxHighlighter {
    private static let rules: [(Regex<Substring>, Color)] = [
        (#/\b(func|var|let|struct|class|enum|protocol|extension|import|if|else|guard|return|switch|case|for|in|while|break|continue|true|false|nil|self|init|throws|async|await)\b/#, .purple),
        (#/"(?:[^"\\]|\\.)*"/#,                                   Color(red: 0.75, green: 0.1,  blue: 0.1)),
        (#/\/\/[^\n]*/#,                                           .gray),
        (#/\b\d+(?:\.\d+)?\b/#,                                   .blue),
        (#/\b[A-Z][A-Za-z0-9]*\b/#,                               Color(red: 0.1, green: 0.45, blue: 0.65)),
    ]

    static func highlight(_ code: String) -> AttributedString {
        var result = AttributedString(code)
        for (pattern, color) in rules {
            for match in code.matches(of: pattern) {
                guard let attrRange = Range(match.range, in: result) else { continue }
                result[attrRange].foregroundColor = color
            }
        }
        return result
    }
}

// MARK: – View

struct SyntaxHighlightedView: View {
    let code: String

    var body: some View {
        ScrollView([.horizontal, .vertical]) {
            Text(SyntaxHighlighter.highlight(code))
                .font(.system(.footnote, design: .monospaced))
                .lineSpacing(4)
                .padding(16)
                .frame(maxWidth: .infinity, alignment: .leading)
        }
        .background(Color(white: 0.10))
        .clipShape(RoundedRectangle(cornerRadius: 12))
    }
}

// MARK: – Preview

#Preview {
    SyntaxHighlightedView(code: """
    import SwiftUI

    // Entry point
    struct ContentView: View {
        let greeting = "Hello, world"
        var count: Int = 42

        var body: some View {
            Text(greeting)
                .font(.title)
        }
    }
    """)
    .padding()
    .preferredColorScheme(.dark)
}

How it works

  1. Wrap in AttributedString. AttributedString(code) creates a mutable attributed string whose character storage mirrors the original String, preserving all indices so Range<String.Index> values can be bridged directly.
  2. Match with Swift Regex literals. The #/…/# literal syntax (Swift 5.7+, iOS 16+) gives you typed, compile-time-checked patterns. String.matches(of:) returns every non-overlapping match in order, which matters when later token types (e.g., type names) would otherwise re-color keyword runs.
  3. Bridge ranges and tint. Range(match.range, in: result) converts a Range<String.Index> to the equivalent Range<AttributedString.Index>. The subscript result[attrRange].foregroundColor writes directly into that character run.
  4. Render for free with Text. SwiftUI's Text natively renders AttributedString, so no UIViewRepresentable wrapper is required. Pair with a ScrollView for both axes to handle wide code lines.

Common pitfalls

Claude Code prompt to generate this

Write a SwiftUI view called SyntaxHighlightedView that takes a plain Swift source string and renders it with syntax highlighting. Use AttributedString for the attributed text and Swift Regex literals (#/…/#) for pattern matching. Apply distinct colors for: keywords (purple), string literals (dark red), line comments (gray), numeric literals (blue), and capitalized type names (teal). Render with Text() in a monospaced font inside a dark-background ScrollView that scrolls both horizontally and vertically. Target iOS 17+, Swift 5.10. Include a #Preview showing a short sample Swift snippet.

Related guides

FAQ

Does this work on iOS 16?

The #/…/# Regex literal syntax and String.matches(of:) were introduced in Swift 5.7 / iOS 16, while AttributedString itself shipped in iOS 15. If you must support iOS 15, replace the Regex literals with NSRegularExpression and bridge results through NSRangeRange<String.Index>Range<AttributedString.Index>. The iOS 17+ minimum lets you use the full modern stack as shown above.

What's the UIKit equivalent?

In UIKit, use NSAttributedString with NSRegularExpression to build a styled attributed string and display it in a UITextView with isEditable = false and isScrollEnabled = true. You can wrap this in SwiftUI via UIViewRepresentable when you need features like text selection or find-in-page that Text does not yet expose.

Last reviewed: 2026-05-12 by the Soarias team.

```