2014年7月24日木曜日

フォルダ階層のローカルファイルをUIWebViewで表示する時のお約束

iOSのプロジェクトで、リソースにHTMLファイルなどのUIWebView用コンテンツを持つ際に、フォルダ階層にして持っておくと便利ですね。

リソースにフォルダを渡す場合、Xcodeの場合は、以下の2つから選ぶことができます。
  • Create groups for any added folders
  • Create folder references for any added folders

一つはグループという、見せかけのフォルダ(!)で、もう一つは、ホントのフォルダです。(笑)

Project Navigatorでは、それぞれ黄色のフォルダと青色のフォルダで表されます。


create_folder.jpg

図のように、コンテンツをローカル(リソース)に持っておけば、同名のファイルを持つこともできますし、以下のコードの様に、ディレクトリを指定してコンテンツを表示させることができます。
NSString *path = [[NSBundle mainBundle] pathForResource:@"privacypolicy" ofType:@"html" inDirectory:@"privacypolicy/jp"];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL fileURLWithPath:path] cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:60];
[_webView loadRequest:request];

ですが、ちょっとハマリポイントもあります。
というか、僕がハマりました。

これ、最初の一回目は気づかないのですが、開発中にはHTMLファイルやCSSファイルなどの修正が入ることがあると思います。

それで修正したファイルをリソースに上書きコピーして、ビルド&実行すると…
あらら?コンテンツが更新されてない。(ヽ´ω`)

って、経験ありませんか?
そこでまず疑うのが、UIWebView というか NSURLCache のキャッシュです。

loadRequestする前に、
[[NSURLCache sharedURLCache] removeCachedResponseForRequest:request];
もしたし、いっそ
[[NSURLCache sharedURLCache] removeAllCachedResponses];
もしてみましたが、ダメでした。

そもそも NSURLRequestインスタンスを作る際に、キャッシュポリシーに NSURLRequestReloadIgnoringLocalAndRemoteCacheData を指定しているので、キャッシュは無視してくれるはずなのです。

そうして次に疑ったのが、コンテンツのパッケージングに失敗している可能性です。
まず、Product > Clean でクリーンしてからビルド&実行すると、見事、コンテンツが更新されて表示されました。

よかった!

じゃない!

いちいち毎度クリーンしてたらビルド時間がはんぱじゃないので、どういうことなのか、もうちょっと調べました。

ファイルをパッケージングし直す判定には、おそらく、ファイルのタイムスタンプが使われているのではないかと思います。タイムスタンプが新しかったらパッケージングし直すという感じです。

最初の図でいうと、privacypolicy.htmlのタイムスタンプが、以前にパッケージングされたファイルのタイムスタンプより新しければ、ビルドした時にパッケージングし直して欲しいわけです。
ですが、ホントのフォルダ階層下(Create folder references for any added folders)にあるファイルの場合だと、ルートのフォルダ(図の場合だとprivacypolicy)のタイムスタンプが更新されていないと、そのフォルダ以下のファイルはビルドしてもパッケージングし直されないようなのです。

試しに、以下のようにターミナルで privacypolicyフォルダのタイムスタンを更新してあげると、プロジェクト全体をクリーンしなくても、パッケージングし直してくれるようになりました。
$ touch privacyplicy/

よかった、よかった!

関連記事

0 件のコメント:

コメントを投稿

Related Posts Plugin for WordPress, Blogger...