SkillAgentSearch skills...

ExtendedSwiftMath

LaTeX math rendering for iOS and macOS with comprehensive symbol coverage, automatic line wrapping, and native Swift implementation. Based on SwiftMath.

Install / Use

/learn @ChrisGVE/ExtendedSwiftMath
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

ExtendedSwiftMath

License: MIT GitHub Release CI SPM Compatible Swift 5.9+ Platforms Documentation

An extended version of SwiftMath with comprehensive LaTeX symbol coverage, adding missing mathematical symbols, blackboard bold, delimiter sizing, amssymb equivalents, and automatic line wrapping.

Credits

This library is based on SwiftMath by Mike Griebling, which itself is a Swift translation of iosMath by Kostub Deshmukh. We gratefully acknowledge their foundational work.

Overview

ExtendedSwiftMath provides a full Swift implementation for displaying beautifully rendered math equations in iOS and macOS applications. It typesets formulae written using LaTeX in a UILabel equivalent class, using the same typesetting rules as LaTeX so equations are rendered exactly as LaTeX would render them.

ExtendedSwiftMath is similar to MathJax or KaTeX for the web but for native iOS or macOS applications without having to use a UIWebView and Javascript. More importantly, it is significantly faster than using a UIWebView.

This library prepackages everything needed for direct access via the Swift Package Manager.

Examples

Here are screenshots of some formulae that were rendered with this library:

x = \frac{-b \pm \sqrt{b^2-4ac}}{2a}

Quadratic Formula Quadratic Formula

f(x) = \int\limits_{-\infty}^\infty\!\hat f(\xi)\,e^{2 \pi i \xi x}\,\mathrm{d}\xi

Calculus Calculus

\frac{1}{n}\sum_{i=1}^{n}x_i \geq \sqrt[n]{\prod_{i=1}^{n}x_i}

AM-GM AM-GM

\frac{1}{\left(\sqrt{\phi \sqrt{5}}-\phi\\right) e^{\frac25 \pi}}
= 1+\frac{e^{-2\pi}} {1 +\frac{e^{-4\pi}} {1+\frac{e^{-6\pi}} {1+\frac{e^{-8\pi}} {1+\cdots} } } }

Ramanujan Identity Ramanujan Identity

More examples are included in EXAMPLES

Fonts

Here are previews of the included fonts:

Requirements

SwiftMath works on iOS 11+ or MacOS 12+. It depends on the following Apple frameworks:

  • Foundation.framework
  • CoreGraphics.framework
  • QuartzCore.framework
  • CoreText.framework

Additionally for iOS it requires:

  • UIKit.framework

Additionally for MacOS it requires:

  • AppKit.framework

Installation

Swift Package Manager

Add ExtendedSwiftMath to your Swift package:

dependencies: [
    .package(url: "https://github.com/ChrisGVE/ExtendedSwiftMath.git", from: "1.0.0")
]

Or add it directly in Xcode via File > Add Package Dependencies using https://github.com/ChrisGVE/ExtendedSwiftMath.git.

Usage

The library provides a class MTMathUILabel which is a UIView that supports rendering math equations. To display an equation simply create an MTMathUILabel as follows:


import SwiftMath

let label = MTMathUILabel()
label.latex = "x = \\frac{-b \\pm \\sqrt{b^2-4ac}}{2a}"

Adding MTMathUILabel as a sub-view of your UIView will render the quadratic formula example shown above.

The following code creates a SwiftUI component called MathView encapsulating the MTMathUILabel:

import SwiftUI
import SwiftMath

struct MathView: UIViewRepresentable {
    var equation: String
    var font: MathFont = .latinModernFont
    var textAlignment: MTTextAlignment = .center
    var fontSize: CGFloat = 30
    var labelMode: MTMathUILabelMode = .text
    var insets: MTEdgeInsets = MTEdgeInsets()

    func makeUIView(context: Context) -> MTMathUILabel {
        let view = MTMathUILabel()
        view.setContentHuggingPriority(.required, for: .vertical)
        view.setContentCompressionResistancePriority(.required, for: .vertical)
        return view
    }

    func updateUIView(_ view: MTMathUILabel, context: Context) {
        view.latex = equation
        let font = MTFontManager().font(withName: font.rawValue, size: fontSize)
        font?.fallbackFont = UIFont.systemFont(ofSize: fontSize)
        view.font = font
        view.textAlignment = textAlignment
        view.labelMode = labelMode
        view.textColor = MTColor(Color.primary)
        view.contentInsets = insets
        view.invalidateIntrinsicContentSize()
    }

    func sizeThatFits(_ proposal: ProposedViewSize, uiView: MTMathUILabel, context: Context) -> CGSize? {
        // Enable line wrapping by passing proposed width to the label
        if let width = proposal.width, width.isFinite, width > 0 {
            uiView.preferredMaxLayoutWidth = width
            let size = uiView.sizeThatFits(CGSize(width: width, height: .greatestFiniteMagnitude))
            return size
        }
        return nil
    }
}

For code that works with SwiftUI running natively under MacOS use the following:

import SwiftUI
import SwiftMath

struct MathView: NSViewRepresentable {
    var equation: String
    var font: MathFont = .latinModernFont
    var textAlignment: MTTextAlignment = .center
    var fontSize: CGFloat = 30
    var labelMode: MTMathUILabelMode = .text
    var insets: MTEdgeInsets = MTEdgeInsets()

    func makeNSView(context: Context) -> MTMathUILabel {
        let view = MTMathUILabel()
        view.setContentHuggingPriority(.required, for: .vertical)
        view.setContentCompressionResistancePriority(.required, for: .vertical)
        return view
    }

    func updateNSView(_ view: MTMathUILabel, context: Context) {
        view.latex = equation
        let font = MTFontManager().font(withName: font.rawValue, size: fontSize)
        font?.fallbackFont = NSFont.systemFont(ofSize: fontSize)
        view.font = font
        view.textAlignment = textAlignment
        view.labelMode = labelMode
        view.textColor = MTColor(Color.primary)
        view.contentInsets = insets
        view.invalidateIntrinsicContentSize()
    }

    func sizeThatFits(_ proposal: ProposedViewSize, nsView: MTMathUILabel, context: Context) -> CGSize? {
        // Enable line wrapping by passing proposed width to the label
        if let width = proposal.width, width.isFinite, width > 0 {
            nsView.preferredMaxLayoutWidth = width
            let size = nsView.sizeThatFits(CGSize(width: width, height: .greatestFiniteMagnitude))
            return size
        }
        return nil
    }
}

Automatic Line Wrapping

SwiftMath supports automatic line wrapping (multiline display) for mathematical content. The implementation uses interatom line breaking which breaks equations at atom boundaries (between mathematical elements) rather than within them, preserving the semantic structure of the mathematics.

Using Line Wrapping with UIKit/AppKit

For direct MTMathUILabel usage, set the preferredMaxLayoutWidth property:

let label = MTMathUILabel()
label.latex = "\\text{Calculer le discriminant }\\Delta=b^{2}-4ac\\text{ avec }a=1\\text{, }b=-1\\text{, }c=-5"
label.font = MTFontManager.fontManager.defaultFont

// Enable line wrapping by setting a maximum width
label.preferredMaxLayoutWidth = 235

You can also use sizeThatFits to calculate the size with a width constraint:

let constrainedSize = label.sizeThatFits(CGSize(width: 235, height: .greatestFiniteMagnitude))

Using Line Wrapping with SwiftUI

The MathView examples above include sizeThatFits() which automatically enables line wrapping when SwiftUI proposes a width constraint. No additional configuration is needed:

VStack(alignment: .leading, spacing: 8) {
    MathView(
        equation: "\\text{Calculer le discriminant }\\Delta=b^{2}-4ac\\text{ avec }a=1\\text{, }b=-1\\text{, }c=-5",
        fontSize: 17,
        labelMode: .text
    )
}
.frame(maxWidth: 235)  // The equation will break across multiple lines

Line Wrapping Behavior and Capabilities

SwiftMath implements two complementary line breaking mechanisms:

1. Interatom Line Breaking (Primary)

Breaks equations between atoms (mathematical elements) when content exceeds the width constraint. This is the preferred method as it maintains semantic integrity.

2. Universal Line Breaking (Fallback)

For very long text within single atoms, breaks at Unicode word boundaries using Core Text with number protection (prevents splitting numbers like "3.14").

See MULTILINE_IMPLEMENTATION_NOTES.md for implementation details and recent changes.

Fully Supported Cases

These atom types work perfectly with interatom line breaking:

✅ Variables and ordinary text:

label.la
View on GitHub
GitHub Stars4
CategoryDevelopment
Updated25d ago
Forks0

Languages

Swift

Security Score

85/100

Audited on Mar 7, 2026

No findings