[iOS] ローカル HTML の読み込み

2014.08.01

車輪開発大好きおたいがです。こんにちは。(挨拶)

とある実務における実話なのですが、下記制限において動作する HTML アプリケーションを作ってほしい…という要望を受けました。

  • http|https:// でアクセスするの禁止
    オフライン環境での動作が必須
  • iOS 端末限定
  • 大人の都合で iOS Developer Program 使用禁止
    UIWebView ラップするだけの自前アプリも NG

作業着手する前から絶望的な状況に立たされていたのですが、無事に乗り切れたので、肝心と思えた点のみ作業備忘録ということで残しておきます。

アプリケーションの選定

iOS 上で動作するブラウザアプリは、ファイルプロトコル (file://) 経由でローカル HTML にアクセスすることができないらしいので、既に世の中に出ているアプリを使用してローカル HTML を読み込むことにしました。

以下の候補は、いずれも iTunes のファイル共有機能を使用することで HTML の受け渡し、および、表示が可能です。

DocAS01

候補 1. DocAS Lite

https://itunes.apple.com/jp/app/docas-lite-pdf-bian-huan-pdf/id451036875

候補 2. DocAS

https://itunes.apple.com/jp/app/docas-pdf-bian-huan-pdf-zhu/id437110885

候補 3. FileApp

https://itunes.apple.com/jp/app/fileapp-file-manager-document/id297804694

DocAS の廉価版である DocAS Lite は、広告が表示されること ( HTML 表示中は表示されない ) と、管理できるドキュメント数に制限があること以外で特に気になる点はありませんでした。また、FileApp も試してみたのですが、<button> 要素をクリックしたときの表示挙動が DocAS と比較して怪しかったので、結果的に DocAS Lite を採用することにしました。( おそらく使用しているエンジンが違うのでしょう )

外部ファイルが読み込めない罠

無事に HTML が表示されたのは確認できましたが、JavaScript、CSS、画像など、外部ファイルを読み込むことができませんでした。なので、単一ソースでアプリケーションを完結させる必要があります。

JavaScript や CSS のコードは HTML に直接書き込めるということは広く知られていると思いますが、画像に関しても同じことが可能です。

データ URI スキームで Base64 形式の画像を読み込む

Google のウェブ検索結果で表示される画像にも採用されているデータ URI スキームを使用して、画像を HTML に埋め込むことにしました。

まずは画像を Base64 形式のに文字列にエンコードします。世の中に転がっているフリーソフトを使うなり、自前でツール作るなり、方法は色々あるので割愛しますが、たとえば私の Twitter アイコン…

taiga

これが以下のような文字列になります。

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
d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAABJRU5ErkJggiAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA=

あとは、変換した Base64 データをデータ URI スキームの書式 [*1] に変換して、<img> 要素に読み込ますだけです。

*1 Data URI scheme - Wikipedia | 書式 より
http://ja.wikipedia.org/wiki/Data_URI_scheme#.E6.9B.B8.E5.BC.8F

data:[][;charset=][;base64],

before

<img src="taiga.png" />

after

<img src="data:image/png;base64,iVBORw0KGg<中略>ICAgICA=" />

これで画像が HTML に埋め込まれます。ただし、HTML の容量が大きくなります。

実際に使用した ( できた ) フレームワーク、機能

すべて、ひとつの HTML に埋め込む必要がありましたが、問題なく動いてくれました。

  • jQuery
  • AngularJS
  • Bootstrap
    Glyphicon の使用可否は不明
  • localStorage
    5MB の容量制限あり

まとめ

自分が思っていた以上に動作してくれました。
たとえば、localStorage にデータを蓄積させるような簡易 Web アプリを構築するときには、この手が意外と使えるかもしれません。

また、厳しい制約の中で試行錯誤するのはなかなか面白いかも…などと思いました。