Swift その2 Advent Calendar 2016 9日目です!
Swift と言いつつ iOS と JavaScript の話がメインになってしまいました
ピーちゃん
ピーちゃんという、 esa.io の iOS クライアントアプリを作っていて、そこで Markdown をアプリ上で表示しています。
その時どうやって Markdown をレンダリングしていったかやり方を書いていきます。
- AppStore: ピーちゃん
- GitHub: starhoshi/pi-chan2
Swift で Markdown
Swift で Markdown をレンダリングしたい時は以下の方法があるかと思います。
- Markdown を自力で Parse して、記法に応じたフォントサイズや太さなどを設定し表示
- SimonFairbairn/SwiftyMarkdown などライブラリを使用
- WebView で JavaScript を使い表示
1 は厳しいというか面倒、2 も何か制限がありあそうだしこれ使っておけば安心というデファクトスタンダードというほどではない。
3 は JS の Markdown ライブラリも豊富にあり良さそう、ということで WebView に Markdown を渡す方式にしました。
WebView で Markdown を表示
- Markdown をレンダリングするための html/js をローカルに用意する
- WebView がその html を読み込む
- html の読み込みが完了したら Markdown を js に渡す
- js が Markdown を解釈しレンダリングする
の手順で読み込んでいきます。
ここでは UIWebView を使っていますが、良い子は WKWebView を使ってください。
1. Markdown をレンダリングするための html/js をローカルに用意する
各ライブラリの取得
Markdown をレンダリングする js ライブラリとして marked.js、 css ライブラリとして github-markdown-css を利用します。
せっかくなので emoji も表示したいですね 。では emojify の js と css もお借りしましょう。
上記の js / css をダウンロードしフォルダに配置します。
また、それらのライブラリを利用する本体の md.html
も作成してしまいましょう。
そうすると、 Xcode にはこのように表示されているはずです。
md.html でライブラリを読み込む
上記で設置した md.html で 各ライブラリを読み込んでいきます。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="text/javascript" src="./emojify.min.js"></script>
<link rel="stylesheet" href="./emojify.min.css">
<script type="text/javascript" src="./marked.js"></script>
<link rel="stylesheet" href="./github-markdown.css">
<script>
function insert(html) {
marked.setOptions({
gfm: true,
tables: true,
breaks: true
});
document.getElementById('content').innerHTML = marked(html);
emojify.setConfig({img_dir: 'https://github.global.ssl.fastly.net/images/icons/emoji/' });
emojify.run(document.getElementById('content'));
}
</script>
</head>
<body>
<article class="markdown-body">
<div id="content" />
</article>
</body>
</html>
各ライブラリの読み込みと function insert(html)
で Markdown を Swift 側から受け取る準備をしています。
ここら辺は marked.js や emojify の使い方になってくるので、詳しくは各ドキュメントを参照ください。
2. WebView がその html を読み込む
ViewController の viewDidLoad などで html を読み込みます。
override func viewDidLoad() {
super.viewDidLoad()
let url = Bundle().url(forResource: "md", withExtension: "html")
let req = URLRequest(url: url)
webView.loadRequest(req)
}
3. html の読み込みが完了したら Markdown を js に渡す
func webViewDidFinishLoad(_ webView: UIWebView) {
setMarkdown()
}
func setMarkdown() {
let markdown = "# h1\\n ## h2 \\n * list\\n * :)"
let js = "insert('\(markdown)');"
self.webView.stringByEvaluatingJavaScript(from: js)
}
webView の stringByEvaluatingJavaScript
を使い、先ほど用意した function insert(html)
で js を実行しています。
ここで少し注意が必要で、 Swift 側で html の読み込みが完了する前に js を実行してしまうと js の実行が失敗してしまうので、 webViewDidFinishLoad
が呼ばれるまで待ちます。
4. js が Markdown を解釈しレンダリングする
無事レンダリングされました
おわり
WebView を使い Markdown をレンダリングする一通りの流れを記載しました。
あまり Swift Advent Clendar とは関係ない話になってしまいましたが 誰かの役に立てればと思います