ぽんぽこ日記

プログラミング、読書、日々の生活

UIWebView内の画面遷移をフックする

常時ネット接続を前提とした今日のスマートフォンであるところのiPhoneでは、サーバと通信することが前提のアプリを作ることが多い。

多くのRSSリーダのように、アプリケーション内部で非同期にサーバと通信して情報を取得し、iPhoneのネイティブのUIを使って情報を表示することも多いが、UIWebViewをつかってアプリ内部にWebブラウザ機能を用意し、HTML画面を表示して直接Webサーバとユーザが対話することも可能だ。


この場合問題になるのは、UIWebViewに制御がある間、ユーザの挙動やWeb画面の遷移はアプリがあまり把握できないことだ。

もちろん、ナビゲーションバーなどにボタンを付けておけば、ユーザはアプリの任意の画面に遷移することは可能だ。しかし、その遷移のタイミングをサーバ側で制御したい場合もある。具体的にはWebブラウザ画面上で、特定のリンクをクリックしたら、iPhoneアプリ側のViewコントローラに制御を戻したい場合だ。

これを実現するには、制御させたいクラス(たいていはビューコントローラ)にUIWebViewDelegateプロトコルをインプリメントし、そのクラスをUIWebViewのdelegateに設定し、
webView:shouldStartLoadWithRequest:navigationType:
を実装すれば、Web画面が遷移するタイミングをフックすることができる。

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
  NSString* URLString = [[[request URL] standardizedURL] absoluteString];
  NSLog(@"shouldStartLoadWithRequest= %@", URLString );
  if( /*何らかのURLパターンマッチングが真*/ ){

  // たとえば、ルートビューに戻す
    [self.navigationController popToRootViewControllerAnimated:YES];

    return NO; // httpリクエストを行わない
  }
  return YES;
}

上の例のように、同メソッドでNOを返すことで、UIWebビューはhttpリクエストを行わない。

アプリ内部からアクセス可能なURLを制限する場合などにも有効だろう。
補記:
XMLHttpRequest()をもちいたJavaScriptからのアクセスでは、同メソッドは呼び出されないようだ。

2012-11-28追記:

続きの応用編を書きました。

UIWebView内の画面遷移をフックする 応用編 - ぽんぽこ日記

2014-09-24追記:
iOS8から導入されたWKWebViewで同様のことをしたい場合について書きました。


【iOS8】 WKWebView内の画面遷移をフックする - ぽんぽこ日記