In this article I am going to show you a method to integrate MathJax - an external javascript display engine for mathematics - in an iOS app. I used the following components:
Component | Version |
---|---|
XCode | Version 7.2.1 (7C1002) |
iOS | 9.2 |
MathJax | 2.6.1 |
Prerequisite
I wanted to display mathematical equations inside an iOS app using existing math render packages. According to this Stack overflow answer, mathML is supported by UIWebView since iOS 5. The downside of this solution, is that you have to use another packages to convert a convenient math equation reprsentation (like LaTEX) to mahtML which is very unconvenient:
<math title="2^(2/(sqrt(6))" xmlns="http://www.w3.org/1998/Math/MathML">
<mstyle mathcolor="blue" fontfamily="sanserif" displaystyle="true">
<msup>
<mn>2</mn>
<mrow>
<mfrac>
<mn>2</mn>
<mrow>
<msqrt>
<mrow>
<mn>6</mn>
</mrow>
</msqrt>
</mrow>
</mfrac>
</mrow>
</msup>
</mstyle>
</math>
The equivalent LaTEX representation is:
2^{\frac{2}{\sqrt{6}}}
To be able to use LaTEX, a third party engine is needed to produce renderable html from it. I chose MathJax for this purpose.
Downloading MathJax
Download the sources from MathJax’s Github page. At the time I wrote this article, the latest version was 2.6.1. It could take quite a bit of time to download the whole zip file.
I put the downloaded files into the Xcode project’s Vendor folder:
Simply unboxed the zip, the package takes up 180 MB space (that’s a lot!). In a future article I will show you the minimal needed content of this package that is be able to render the expressions.
Adding the MathJax package to the project
I added the downloaded and extracted MathJax sources to a single view based Xcode project, by dragging the folder into the project navigator. I unchecked the copy sources option.
Using the MathJax package
After the sources are placed to the right place, it’s time to use them. I draged a UIWebView to the Storyboard, and created a connection to the ViewController class (@IBOutlet weak var myWebView: UIWebView!
). I wanted to display the following simple html page in the UIWebView…
<!DOCTYPE html>
<html>
<head>
<title>MathJax TeX Test Page</title>
<script type="text/javascript" async
src="MathJax-2.6.1/MathJax.js?config=TeX-AMS_CHTML">
</script>
</head>
<body>
<div style="font-size: 30pt; color: #eee;">
$$
\begin{equation}
\prod_{\substack{
1\le i \le n\\
1\le j \le m}}
M_{i,j}
\end{equation}
$$
</div>
</body>
</html>
… so I used its loadHTMLString
method to do that:
//
// ViewController.swift
// MathJaxTest01
//
// Created by Tibor Simon on 20/02/16.
// Copyright © 2016 Tibor Simon. All rights reserved.
//
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var myWebView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let path = NSBundle.mainBundle().bundlePath
let baseURL = NSURL.fileURLWithPath(path)
let myHTML = "<!DOCTYPE html><html><head><title>MathJax TeX Test Page</title><script type=\"text/javascript\" async src=\"MathJax-2.6.1/MathJax.js?config=TeX-AMS_CHTML\"></script></head><body> <div style=\"font-size: 30pt; color: #eee;\">$$\\begin{equation}\\prod_{\\substack{1\\le i \\le n\\\\ 1\\le j \\le m}}M_{i,j} \\end{equation}$$</div></body></html>"
myWebView.loadHTMLString(myHTML, baseURL:baseURL)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Testing with the simulator
The project loads up to the simulator a bit slowly. After it loads, it renders the mathematical expression to the UIWebView in 8 phases:
The whole rendering happens in less then half a second, but it is noticeable. If you want to use this method to render mathematical expresions in your app, you have to make sure, you only show your UIWebView, when it fulli loaded.
Try it out yourself!
You can download the whole Xcode project with the added MathJax sources from the project’s Github repository.
Acknowledgement
For this project, I get a lot of ideas from New 2 Objective-C blog. His implementation is based on a local file writing and reading, which is pretty slow, but it works :)
I also used some ideas from Stack Overflow to make my UIWebView transparent