プログラマでありたい

おっさんになっても、プログラマでありつづけたい

UIWebViewでWebサイトとネイティブアプリを連携する方法について

 iOSによるiPhone/iPadのネイティブアプリで、サーバサイドのプログラミングと連携するケースは割とあるかと思います。その場合に、iPhone/iPadで表示する一部の機能についてはサーバサイドでサクッと作ってしまって、UIWebViewで呼ぶという方法は有力な手段の一つです。ここで問題となるのが、サーバ側とiOS側の連携だと思います。幾つか方法はあるのですが、簡単に実現出来るものを紹介したいと思います。


 連携の方法としては、iPhone/iPadからWebページの制御とWebページからiPhone/iPadの2通りがあると思います。今回は、WebページからiPhone/iPadのケースを紹介します。
大まかな流れとしては、次の3つの順番になります。

  1. UIWebViewのDelegateを使って、画面処理のイベントを取得する
  2. UIWebViewのメソッドのstringByEvaluatingJavaScriptFromStringを使って、JavaScriptを利用してWebサーバ側のHTMLを取得する
  3. HTMLの中から任意のコードを取得し、それを元に処理を実装する

1.UIWebViewのDelegateを使って、画面処理のイベントを取得する



 UIWebViewのイベントを拾うDelegateメソッドに、次の2つのメソッドがあります。

(void)webViewDidStartLoad:(UIWebView *)webView;
(void)webViewDidFinishLoad:(UIWebView *)webView;

 webViewDidStartLoadは、読み込みが始まったタイミング。webViewDidFinishLoadは、読み込み完了のタイミングで呼ばれます。今回の場合ですと、webViewDidFinishLoadで処理を実装すれば良いです。また画面の表示の制御等を行いたければ、webViewDidStartLoadでYes/Noのアラート画面を出せば表示制御が出来ます。

2.UIWebViewのメソッドのstringByEvaluatingJavaScriptFromStringを使って、JavaScriptを利用してWebサーバ側のHTMLを取得する



 UIWebViewのメソッドにstringByEvaluatingJavaScriptFromStringというのがあります。これはUIWebView上でJavaScriptを実行する為のメソッドですが、逆にJavaScriptが動かせるのでHTMLの内容を取得するといったことが可能になります。今回は、この機能を使ってWebサーバ側のHTMLからiOSアプリで実行させたいコードを取得します。HTML全体を取得するには、次のようなコードで実現出来ます。

[webView stringByEvaluatingJavaScriptFromString:@"document.body.innerHTML"]

3.HTMLの中から任意のコードを取得し、それを元に処理を実装する



 HTML全体を取得出来るので、後はパースして所定の部分を切り出せば何とでも出来ます。ただそれだとパース処理が面倒くさいので、例えばMetaタグの中に特定の名前で埋め込んでそこだけを取得するようにすると簡単に実装出来ます。次の例は、metaタグ中にnative-commandという名前で埋め込んでおく例です。もちろんmetaタグじゃなくても良いですし、nameも任意のものを指定できます。

- (void)webViewDidFinishLoad:(UIWebView *)webView{
    //format-detection, native-cooperation
    NSString *htmlCode = [webView stringByEvaluatingJavaScriptFromString:
                      @"function a(){l=document.getElementsByTagName('meta');for(i=0;i<=l.length;i++){if(l[i].name=='native-command') return l[i].content}};a();"];
    //htmlから取得した内容に対する処理の実装
}

まとめ



 上記のようにUIWebViewを使ってサクッとWebアプリとネイティブアプリの連携が可能となります。アプリを突き詰めていくとUIWebViewではなく全部ネイティブアプリとなることも多いのですが、開発期間や開発者の得手不得手を元にサーバサイドで実装するというのも現実的な選択肢です。その際の狭間の部分に今回のような連携手段は有効なんではと考えています。またiOS⇒Webアプリの実装についても、stringByEvaluatingJavaScriptFromStringを使うことによって大抵何でも出来ます。是非、お試しあれ。Enjoy!



See Also:
Objective-Cで、プライベートメソッド・プロパティにアクセスし、ユニットテストを実行する方法
リリース済みのiPhone/iPadアプリのDBの変更の仕方 或いはCoreDataを使ってスキーマの自動マイグレーション


参照:
iphone sdk - stringByEvaluatingJavaScriptFromString causing EXC_BAD_ACCESS - Stack Overflow
F's Garage @fshin2000 :iPhoneとWebサービスの連携手法
UIWebViewでWebとネイティブを相互連携させる方法について - プログラミングノート