[XCODE] UIWebViewでWebページを表示した際にJSのconsole.logの内容を表示する方法
こんにちは、@yoheiMuneです。
今日は、UIWebViewベースのアプリケーションのデバッグに役立つ、 window.cosole.logの内容をXCODEのコンソールに出力する方法を書きたいと思います。

通常のWebページ開発では、Chromeのデベロッパーツールや、iPhone用のWebインスペクタ(詳細は、こちらを参照)を用いて開発する事で、効率的にデバッグする事が可能です。
しかしUIWebViewで表示するWebページのデバッグはJSのログとか見えないので、デバッグしづらい。
その解決策はいくつかありますが、今回はJavaScriptのwindow.console.logをXCODEのコンソールに出力して、 デバッグ情報を入手しやすくする方法を紹介したいと思います。
なお以下で紹介する方法は、Stack Overflowで紹介された内容を発展させた内容となります。
JavaScriptとObjective-Cで、それぞれ以下の実装を行います。
上記で「UIWebViewの場合は」という分岐を入れる理由は、 通常だと「ios-log:#iOS#xxx」というリクエストはエラー扱いになってしまい、 その後のJavaScript実行が中止されてしまうので、それを避けるためです。
UIWebViewを利用しているか否かは、UserAgentの上書き(詳しくはこちら)などを利用して判別することが出来ます。
リクエストを補足するために、UIWebViewのDelegateを利用します。
今回はその機能を利用して、ログ出力用のリクエストの場合はキャッチして、XCODEのコンソールにログ出力をします。
JSで意図しないエラーが発生した場合(それもwondow.logを仕込んでいない箇所で)に、 ログも出ないし、画面も動かないし、何が悪いのかを特定するのが大変です。
そのため、エラー発生時のログ出力もJS側に実装するといいかと思います。
以下が実装例です。
こんな感じで少しずつでもデバッグを楽にすることが、作業の効率化に繋がるんだなぁと思っています。
より快適なデバッグ生活を求めて、これからも活動して、良き内容があればまたブログに書きたいと思います。
最後までご覧頂きましてありがとうございました。
今日は、UIWebViewベースのアプリケーションのデバッグに役立つ、 window.cosole.logの内容をXCODEのコンソールに出力する方法を書きたいと思います。

UIWebViewベースのアプリはデバッグしづらい?
UIWebViewベースのアプリを開発する際に、デバッグがしづらいという問題点があります。通常のWebページ開発では、Chromeのデベロッパーツールや、iPhone用のWebインスペクタ(詳細は、こちらを参照)を用いて開発する事で、効率的にデバッグする事が可能です。
しかしUIWebViewで表示するWebページのデバッグはJSのログとか見えないので、デバッグしづらい。
その解決策はいくつかありますが、今回はJavaScriptのwindow.console.logをXCODEのコンソールに出力して、 デバッグ情報を入手しやすくする方法を紹介したいと思います。
なお以下で紹介する方法は、Stack Overflowで紹介された内容を発展させた内容となります。
JavaScriptで出力するログをXCODEのコンソールに表示する
XCODEのコンソールにJavaScriptのwindow.console.logを出力することで、デバッグをしやすくすることが出来ます。JavaScriptとObjective-Cで、それぞれ以下の実装を行います。
- JavaScriptでXCODEでログ出力する為のリクエストを発信する。
- UIWebViewでログ出力用のリクエストを補足して、内容をコンソールに出力する。
JavaScriptでXCODEでログ出力する為のリクエストを発信する
javaScript側では、以下のように行うことで、UIWebViewに向けたリクエストを発信します。
// window.console.logを上書きすると動かない場合もあるので、
// 今回は新しいメソッドを定義する。
window.log = function(msg) {
// まずは通常通りのログ出力を行う。
console.log(msg);
// UIWebViewを用い手居る場合には、
// XCODEのコンソールにも出力する仕組みを導入する。
if (isUIWebView && debug) {
var iframe = document.createElement("IFRAME");
iframe.setAttribute("src", "ios-log:#iOS#" + msg);
document.documentElement.appendChild(iframe);
iframe.parentNode.removeChild(iframe);
iframe = null;
}
}
UIWebViewの場合は。「ios-log:#iOS#xxx」というリクエストを発信します。上記で「UIWebViewの場合は」という分岐を入れる理由は、 通常だと「ios-log:#iOS#xxx」というリクエストはエラー扱いになってしまい、 その後のJavaScript実行が中止されてしまうので、それを避けるためです。
UIWebViewを利用しているか否かは、UserAgentの上書き(詳しくはこちら)などを利用して判別することが出来ます。
UIWebViewでログ出力用のリクエストを補足して、内容をコンソールに出力する
JavaScriptでUIWebView向けに発信したリクエストをUIWebViewで細くすることで、 リクエストに含まれるログ内容をXCODEのコンソールに出力します。リクエストを補足するために、UIWebViewのDelegateを利用します。
- (BOOL)webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType {
// リクエストに「ios-log:#iOS#」が含まれる場合には、リクエストをキャッチする。
NSString* nextUrl=[[request URL] absoluteString];
NSRange range;
if ((range=[nextUrl rangeOfString:@"ios-log:"]).location!=NSNotFound) {
// リクエスト内容から、ログ内容を取得する。
NSString *iOSLog = [nextUrl stringByReplacingOccurrencesOfString:@"ios-log:"withString:@""];
// 文字列はパーセントエスケープされているので、デコードする。
iOSLog = [iOSLog stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(@"%@",iOSLog);
// このリクエストは、ここで中断する。
returnNO;
}
// 上記以外のリクエストは、そのまま発信する。
return YES;
}
UIWebViewDelegateの「shouldStartLoadWithRequest」のメソッドを利用することで、
実際にサーバーにリクエストを送る前に、内容を精査して中止することが出来ます。今回はその機能を利用して、ログ出力用のリクエストの場合はキャッチして、XCODEのコンソールにログ出力をします。
エラー情報も出力する
上記でだいぶデバッグしやすくなるのですが、少し足りない。JSで意図しないエラーが発生した場合(それもwondow.logを仕込んでいない箇所で)に、 ログも出ないし、画面も動かないし、何が悪いのかを特定するのが大変です。
そのため、エラー発生時のログ出力もJS側に実装するといいかと思います。
以下が実装例です。
window.onerror = function(errMsg, url, lineNumber) {
window.log(errMsg + ", file=" + url + ":" + lineNumber);
}
上記の実装で、エラー原因とエラー箇所がログに出力されるので、デバッグしやすくなります。最後に
組み込みのプログラムをデバッグすることは、比較的難しい。こんな感じで少しずつでもデバッグを楽にすることが、作業の効率化に繋がるんだなぁと思っています。
より快適なデバッグ生活を求めて、これからも活動して、良き内容があればまたブログに書きたいと思います。
最後までご覧頂きましてありがとうございました。






