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.
The EXAMPLES.md file contains more examples.
iosMath requires iOS 18+ or macOS 15+. It depends on the following
Apple frameworks: Foundation, CoreGraphics, QuartzCore, CoreText, and
UIKit (iOS) or AppKit (macOS).
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"]
),
]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];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
}
}
#endifThen 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.
- 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
\leftand\right) - Greek alphabet
- Combinatorics (
\binom,\chooseetc.) - 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
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'
MTMathUILabel supports Display mode (equivalent to $$ in LaTeX) and Text
mode (equivalent to $). The default is Display. To switch:
label.mode = .textObjective-C
label.labelMode = kMTMathUILabelModeText;The default alignment is left. To center or right-align:
label.textAlignment = .centerObjective-C
label.textAlignment = kMTTextAlignmentCenter;The default font size is 20pt:
label.fontSize = 30The 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];label.textColor = .redTo 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 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);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]];If the LaTeX string is invalid or uses unsupported commands, the error is displayed inline by default. To suppress it:
label.displayErrorInline = falseRetrieve the error programmatically:
label.latex = #"\badcommand"#
if let error = label.error {
print(error.localizedDescription)
}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.
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)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 = mathListMTMathList 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")- Support for explicit big delimiters (
\bigl,\bigr, etc.) - Additional plain TeX commands
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)
- MathEditor: A WYSIWYG math editor for iOS.
- MathSolver: A library for solving math equations.
iosMath is available under the MIT license. See the LICENSE file for details.
The following fonts are bundled with this distribution:
- Latin Modern Math: GUST Font License
- Tex Gyre Termes: GUST Font License
- XITS Math: Open Font License



