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/ExtendedSwiftMathREADME
ExtendedSwiftMath
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}

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

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

\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} } } }

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
