Skip to content

kostub/iosMath

Repository files navigation

iosMath

License

iosMath is a library for displaying beautifully rendered math equations in iOS and macOS applications. It typesets formulae written using LaTeX in a UIView/NSView subclass, using the same typesetting rules as TeX so equations look exactly as LaTeX would render them — no WebView required.

It is similar to MathJax or KaTeX for the web but for native iOS or macOS applications, and significantly faster than a UIWebView.

Examples

Quadratic Formula

Calculus

AM-GM

Ramanujan Identity

The EXAMPLES.md file contains more examples.

Requirements

iosMath requires iOS 18+ or macOS 15+. It depends on the following Apple frameworks: Foundation, CoreGraphics, QuartzCore, CoreText, and UIKit (iOS) or AppKit (macOS).

Installation

iosMath is distributed via Swift Package Manager.

In Xcode: File → Add Package Dependencies… and enter the repository URL.

In Package.swift:

dependencies: [
    .package(url: "https://github.com/kostub/iosMath.git", from: "2.0.0"),
],
targets: [
    .target(
        name: "YourTarget",
        dependencies: ["iosMath"]
    ),
]

Usage

Simple usage — UIKit / AppKit

Create an MTMathUILabel, set its latex property, and add it as a subview:

import iosMath

let label = MTMathUILabel()
label.latex = #"x = \frac{-b \pm \sqrt{b^2-4ac}}{2a}"#
view.addSubview(label)
Objective-C
@import iosMath;

MTMathUILabel *label = [[MTMathUILabel alloc] init];
label.latex = @"x = \\frac{-b \\pm \\sqrt{b^2-4ac}}{2a}";
[self.view addSubview:label];

Simple usage — SwiftUI

MTMathUILabel is a UIView/NSView subclass. Wrap it for SwiftUI using UIViewRepresentable / NSViewRepresentable:

import SwiftUI
import iosMath

#if os(iOS)
struct MathView: UIViewRepresentable {
    let latex: String
    func makeUIView(context: Context) -> MTMathUILabel { MTMathUILabel() }
    func updateUIView(_ view: MTMathUILabel, context: Context) {
        view.latex = latex
    }
}
#elseif os(macOS)
struct MathView: NSViewRepresentable {
    let latex: String
    func makeNSView(context: Context) -> MTMathUILabel { MTMathUILabel() }
    func updateNSView(_ view: MTMathUILabel, context: Context) {
        view.latex = latex
    }
}
#endif

Then use it in any SwiftUI view:

MathView(latex: #"e^{i\pi} + 1 = 0"#)
    .frame(height: 50)

A complete cross-platform SwiftUI wrapper with font, color, and alignment support is available in SwiftMathExample/MathLabel.swift.

Supported formula types

  • Simple algebraic equations
  • Fractions and continued fractions
  • Exponents and subscripts
  • Trigonometric formulae
  • Square roots and n-th roots
  • Calculus symbols — limits, derivatives, integrals
  • Big operators (e.g. product, sum)
  • Big delimiters (using \left and \right)
  • Greek alphabet
  • Combinatorics (\binom, \choose etc.)
  • Geometry symbols (e.g. angle, congruence etc.)
  • Ratios, proportions, percents
  • Math spacing
  • Overline and underline
  • Math accents
  • Matrices
  • Equation alignment
  • Bold, roman, caligraphic and other font styles (\bf, \text, etc.)
  • Most commonly used math symbols
  • Colors

Example app

A runnable Swift example app is in SwiftMathExample/. It has two tabs: a curated Examples tab showing named formulae, and a Gallery tab with the full rendering test suite.

Open SwiftMathExample.xcodeproj in Xcode, or build from the command line:

xcodebuild build -project SwiftMathExample.xcodeproj \
  -scheme SwiftMathExample \
  -sdk iphonesimulator \
  -destination 'platform=iOS Simulator,name=iPhone 16'

Advanced configuration

Math mode

MTMathUILabel supports Display mode (equivalent to $$ in LaTeX) and Text mode (equivalent to $). The default is Display. To switch:

label.mode = .text
Objective-C
label.labelMode = kMTMathUILabelModeText;

Text alignment

The default alignment is left. To center or right-align:

label.textAlignment = .center
Objective-C
label.textAlignment = kMTTextAlignmentCenter;

Font size

The default font size is 20pt:

label.fontSize = 30

Font

The default font is Latin Modern Math. Three fonts are bundled; you can also use any OTF math font:

label.font = MTFontManager().termesFont(withSize: 20)
Objective-C
label.font = [[MTFontManager fontManager] termesFontWithSize:20];

Color

label.textColor = .red

To change the color of individual parts of the equation, access label.displayList and set textColor on the specific display nodes.

Objective-C
label.textColor = [UIColor redColor];

Content insets

Content insets add padding between the rendered equation and the edges of the label's bounds. This is useful when the label sits flush against other elements and you need breathing room without adding a wrapper view:

// Add 10 pt of space on the left and 20 pt on the right.
label.contentInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 20)

On macOS, use NSEdgeInsets instead of UIEdgeInsets.

Objective-C
label.contentInsets = UIEdgeInsetsMake(0, 10, 0, 20);

Custom commands

Define custom LaTeX commands (similar to macros):

MTMathAtomFactory.addLatexSymbol(
    "lcm",
    value: MTMathAtomFactory.largeOperator(named: "lcm", limits: false)
)

This makes \lcm available in any LaTeX string passed to MTMathUILabel.

Objective-C
[MTMathAtomFactory addLatexSymbol:@"lcm"
                            value:[MTMathAtomFactory operatorWithName:@"lcm" limits:NO]];

Error handling

If the LaTeX string is invalid or uses unsupported commands, the error is displayed inline by default. To suppress it:

label.displayErrorInline = false

Retrieve the error programmatically:

label.latex = #"\badcommand"#
if let error = label.error {
    print(error.localizedDescription)
}

Advanced usage — programmatic math model

For editors and other programmatic use cases you can build and inspect the math model directly using MTMathList and related types, bypassing the LaTeX parser entirely.

Parsing LaTeX

import iosMath

// Returns nil if the string cannot be parsed.
if let list = MTMathListBuilder.build(from: #"x^2 + y^2 = z^2"#) {
    for atom in list.atoms {
        print(atom.type, atom.nucleus)
    }
}

Convert an MTMathList back to LaTeX:

let latex = MTMathListBuilder.mathList(toString: list)

Building a list programmatically

import iosMath

// Build a fraction 1/2 without parsing LaTeX.
let num   = MTMathListBuilder.build(from: "1")!
let denom = MTMathListBuilder.build(from: "2")!
let frac  = MTMathAtomFactory.fraction(numerator: num, denominator: denom)

let mathList = MTMathList()
mathList.add(frac)

let label = MTMathUILabel()
label.mathList = mathList

Atom types and the math model

MTMathList is a linked list of MTMathAtom objects. Each atom has a type (MTMathAtomType) that determines its rendering and spacing. Subclasses carry additional structure:

Type Class Description
Fraction MTFraction Numerator and denominator lists
Radical MTRadical Radicand and optional degree
Large operator MTLargeOperator \sum, \int, etc. with limits
Inner MTInner Embedded list with optional delimiters
Accent MTAccent \hat, \vec, etc.

Use MTMathAtomFactory to construct atoms:

let times     = MTMathAtomFactory.times()         // ×
let frac      = MTMathAtomFactory.fraction(numerator: num, denominator: denom)
let sqrt      = MTMathAtomFactory.placeholderSquareRoot()
let alpha     = MTMathAtomFactory.atom(forLatexSymbol: "alpha")

Future enhancements

  • Support for explicit big delimiters (\bigl, \bigr, etc.)
  • Additional plain TeX commands

Migration from 0.9.x

Version 2.0.0 is a breaking release. The following changes are required when upgrading from 0.9.x:

  • Deployment targets raised: iOS 18+ and macOS 15+ are now required (previously iOS 9+ / macOS 10.12+).
  • CocoaPods support removed: distribution is via Swift Package Manager only.
  • Swift API renames (Objective-C names are unchanged)

Related projects

License

iosMath is available under the MIT license. See the LICENSE file for details.

Fonts

The following fonts are bundled with this distribution:

About

Beautiful math equation rendering on iOS and MacOS

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors