Edited at

UIWebViewのデバッグ効率を少しでもあげる方法(Log編)

More than 5 years have passed since last update.

iOS6からはWebインスペクタを使用してJSのデバッグできますが

iOS5に関してはWebインスペクタ使えないんでJSのデバッグきついです。。。

せめてconsole.logの内容をx-codeから確認したい!

ということで以下の手順でログを出力しましょう。

用意するもの

・jquery

・NSURLProtocol

・jsファイル(app.js、native-func.js)

・html

1.console.logを置き換えよう

どうせならconsole.logを実行したタイミングで特に何もせずに

出力したいので置き換えましょう。


app.js

if (!window.App) App = {};

App.Native = {};

if(typeof $ !== "undefined") {
// ios6のキャッシュ対策.
$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
options.data = jQuery.param($.extend(originalOptions.data||{}, {
timeStamp: new Date().getTime()
}));
});
}

// console.logの置き換え.
console.log_org = console.log;
console.log = function(message){
App.Native.log(message);
return console.log_org.apply(this, arguments);
}


2.log出力用のjsを用意する

ログ出力用のURLとパラメータを決めてそれをgetで読み込ませましょう。

今回はURLを「native-func/log」、パラメータをmessageとしてます。


native-func.js

App.Native = (function($) {

var _log = function(message) {
message = encodeURIComponent(message);
$.get('/native-func/log?message=' + message);
};
return {
log:_log
};
}(jQuery));

3.native側でログ用の命令を処理しよう

NSURLProtocolを継承して独自のProtocolを実装して

ログを吐き出しましょう


NativeFuncProtocol.h

#import <Foundation/Foundation.h>

@interface NativeFuncProtocol : NSURLProtocol
@end


NativeFuncProtocol.m

#import "NativeFuncProtocol.h"


static NSString* const NATIVE_FUNC_IDENTIFIER = @"native-func";

@implementation NativeFuncProtocol

+(BOOL) canInitWithRequest:(NSURLRequest *)request {
NSArray* pathComponents = request.URL.pathComponents;
// ログ出力の場合はこのProtocolで処理する.
if(pathComponents.count == 3 && [pathComponents[1] isEqualToString:NATIVE_FUNC_IDENTIFIER]){
return YES;
}
return NO;
}

+(NSURLRequest*) canonicalRequestForRequest:(NSURLRequest *)request {
return request;
}

-(void) startLoading {
NSArray* pathComponents = self.request.URL.pathComponents;
if(pathComponents.count == 3 && [pathComponents[2] isEqualToString:@"log"]) {
NSArray* param = [self.request.URL.query componentsSeparatedByString:@"&"];
NSArray* messageParam = [param[0] componentsSeparatedByString:@"="];
NSString* message = [self urlDecode:messageParam.lastObject];

// ログ出力.
NSLog(@"WebLog %@", message);

NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:[self.request URL]
statusCode:200
HTTPVersion:@"1.1"
headerFields:nil];
[[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
[self.client URLProtocol:self didLoadData:nil];
[self.client URLProtocolDidFinishLoading:self];
}
}

-(void) stopLoading {
}

-(NSString*) urlDecode:(NSString*)url {
return (__bridge_transfer NSString *)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(
kCFAllocatorDefault,
(__bridge CFStringRef)url,
CFSTR(""),
kCFStringEncodingUTF8);
}
@end


4.1-3で用意したものを組み合わせて見ましょう


empty.html

<!DOCTYPE html>

<head>
<meta charset="utf-8">
<title>TEST</title>
<script src="jquery-2.0.3.min.js"></script>
<script src="app.js"></script>
<script src="native-func.js"></script>
</head>
<body>
<div id="log-button">Log出すよ.</div>
<script>
$(function(){
$("#log-button").on("click", function(){
console.log("ログ出力するよー");
});
});
</script>
</body>
</html>

5.x-codeのdebug consoleを確認してみよう

無事に出ましたね(2回出てるのは2回押したからです。。。)

スクリーンショット 2013-08-11 3.58.50.png

今回のコードは特にセキュリティとか、意図してないパラメータは考慮してませんので、実際使う場合はきちんとその辺りをきれいにしてください。

これで多少はデバッグ効率があがると思います。

あとは既存のNative側のログとWebからのLogを見やすくするために

プラグインやLibraryを入れて対応するとさらによくなると思います。

私の環境ではXcodecolors入れてログの可読性をあげてます。

XcodeColors

最後に今回のProjectをあげておきますので

よろしければ色々触ってみてください。

物置