UIWebViewに表示されたHTMLととアプリケーションとを連携させる方法を紹介します。
本記事で紹介する方法としては、HTML(UIWebViewオブジェクト)からアプリケーションへ通知をおこない、それをトリガーとしてアプリケーション側からHTML(UIWebViewオブジェクト)のfunctionを実行させています。
アプリケーションからHTMLへ何らかのアクションをおこなう場合には、以下のメソッドを利用することが可能です。
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
UIWebViewには、リンクをクリックしてページ遷移をおこなう直前に「本当にページ遷移をおこなってよいのかどうか?」を検証することが可能なデリゲートが用意されています。
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
iOSにはアプリケーションへ直接文字列を渡す方法が用意されていませんので、故意にページ遷移を発生させ、クエリ文字列にアプリケーションへ渡したい文字列を追加し、遷移先のURLをshouldStartLoadWithRequest:navigationType:メソッド
で受け取り、ページ遷移を拒否します。
HTML側で準備させること
HTMLでは、2つのJavaScriptのfunctionを定義しています。
notifyメソッドは、ch3coohスキームで始まる「ch3cooh://notify?msg=sakusan」へ遷移しようとします。[通知をおこなう]というリンクをクリックすると、実行されます。
replaceHtmlメソッドは、アプリケーションから呼び出されるのを期待しているメソッドで、渡された文字列をdivタグを書き換えるだけのものです。
<html> <head> <script type="text/javascript"> function notify(msg) { result.innerHTML = '応答待ち'; document.location = 'ch3cooh://notify?msg=' + msg; } function replaceHtml(parm1) { result.innerHTML = parm1; } </script> </head> <body> <a href="javascript:void(0);" onclick="notify('sakusan');">通知をおこなう</a> <div id="result"> None Data. </div> </body> </html>
アプリケーション側の実装
まずはUIWebViewに先ほど作成したテストページを表示させます。
- (void)viewDidAppear:(BOOL)animated { // テストページを読み込む NSURL* url = [NSURL URLWithString:@"https://dl.dropbox.com/u/2258039/send/sample/ios_notify.html"]; [self.contentView loadRequest:[NSURLRequest requestWithURL:url]]; }
[通知をおこなう]というリンクをクリックすると、document.locationを変更するのでページ遷移が発生します。
// ページ遷移が発生したら実行される - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { // ch3coohスキーマ以外は通常にページ遷移をさせる NSString* scheme = [[request URL] scheme]; if (![scheme isEqualToString:@"ch3cooh"]) { return YES; } // クエリ文字列をパースする NSString* query = [[request URL] query]; NSMutableDictionary *params = [[NSMutableDictionary alloc] init]; for (NSString *param in [query componentsSeparatedByString:@"&"]) { NSArray *elts = [param componentsSeparatedByString:@"="]; if([elts count] < 2) continue; [params setObject:[elts objectAtIndex:1] forKey:[elts objectAtIndex:0]]; } // アプリから送信されたメッセージを受信する NSString* message = [params valueForKey:@"msg"]; NSLog(@"%@", message); // 遅延実行させる [self performSelector:@selector(notificationHtmlFunction:) withObject:message afterDelay:10]; // ch3coohスキーマの場合はページ遷移させない return NO; }
1秒待ってからnotificationHtmlFunctionメソッドが実行されます。実行されるまでの間、「応答待ち」を表示させていたので下図のように表示されます。
notificationHtmlFunctionメソッド
では、シンプルに既存のJavaScriptのメソッド呼び出しをおこなうだけです。
// HTML側で定義されているfunctionを引数付きで実行する - (void)notificationHtmlFunction:(NSString*)message { NSString* msg = [NSString stringWithFormat:@"received:%@", message]; NSString* script = [NSString stringWithFormat:@"replaceHtml('%@');", msg]; [self.contentView stringByEvaluatingJavaScriptFromString:script]; }
上記のコードが実行されると、HTMLの文字列を変更します。下図のように表示されます。
以上で、iOSでのアプリケーションからUIWebView(HTML)へ文字列を送る方法と、UIWebView(HTML)から送られてきた文字列をアプリケーション側で受け取る方法をご紹介させていただきました。
ソースコード
このエントリにて紹介したサンプルプロジェクトはGitHubにて公開しております。