iOS6からはWebインスペクタを使用してJSのデバッグできますが
iOS5に関してはWebインスペクタ使えないんでJSのデバッグきついです。。。
せめてconsole.logの内容をx-codeから確認したい!
ということで以下の手順でログを出力しましょう。
用意するもの
・jquery
・NSURLProtocol
・jsファイル(app.js、native-func.js)
・html
1.console.logを置き換えよう
どうせならconsole.logを実行したタイミングで特に何もせずに
出力したいので置き換えましょう。
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としてます。
App.Native = (function($) {
var _log = function(message) {
message = encodeURIComponent(message);
$.get('/native-func/log?message=' + message);
};
return {
log:_log
};
}(jQuery));
3.native側でログ用の命令を処理しよう
NSURLProtocolを継承して独自のProtocolを実装して
ログを吐き出しましょう
#import <Foundation/Foundation.h>
@interface NativeFuncProtocol : NSURLProtocol
@end
#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で用意したものを組み合わせて見ましょう
<!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回押したからです。。。)
今回のコードは特にセキュリティとか、意図してないパラメータは考慮してませんので、実際使う場合はきちんとその辺りをきれいにしてください。
これで多少はデバッグ効率があがると思います。
あとは既存のNative側のログとWebからのLogを見やすくするために
プラグインやLibraryを入れて対応するとさらによくなると思います。
私の環境ではXcodecolors入れてログの可読性をあげてます。
最後に今回のProjectをあげておきますので
よろしければ色々触ってみてください。