Local MathJax in iOS apps
2016. 02. 20.
Integrating MathJax locally in an iOS app to be able to use mathematical equations stored in LaTEX.

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.

Location of the downloaded MathJax sources.
Fig 1: Location of the downloaded MathJax sources.
Size of the freshly downloaded package.
Fig 2: Size of the freshly downloaded package.

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.

Adding the sources to the project.
Fig 3: Adding the sources to the project.
Unchecking the copy items if needed option.
Fig 4: Unchecking the copy items if needed 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:

Rendering phase 1: It starts as a blank screen.
Fig 5: Rendering phase 1: It starts as a blank screen.
Rendering phase 2: Then it loads the raw LaTEX source.
Fig 6: Rendering phase 2: Then it loads the raw LaTEX source.
Rendering phase 3: First rendering pass.
Fig 7: Rendering phase 3: First rendering pass.
Rendering phase 4: Loading CommonHTML sources for the final rendering pass.
Fig 8: Rendering phase 4: Loading CommonHTML sources for the final rendering pass.
Rendering phase 5: Renders final image.
Fig 9: Rendering phase 5: Renders final image.
Rendering phase 6: Becames blank again.
Fig 10: Rendering phase 6: Becames blank again.
Rendering phase 7: Final image appears in fractions.
Fig 11: Rendering phase 7: Final image appears in fractions.
Rendering phase 8: Render finished.
Fig 12: Rendering phase 8: Render finished.

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

Discussion