web-dev-qa-db-ja.com

iOS UIWebViewのJavascript console.log()

UIWebViewを使用してiPhone/iPadアプリを作成する場合、コンソールは表示されません。 この優れた答え はエラーをトラップする方法を示していますが、console.log()も使用したいと思います。

79
TinkerTank

Javascriptを使用してアプリのデバッグコンソールにログを記録するソリューションがあります。少し粗雑ですが、動作します。

まず、javascriptでconsole.log()関数を定義します。この関数は、ios-log:urlでiframeを開いてすぐに削除します。

// Debug
console = new Object();
console.log = function(log) {
  var iframe = document.createElement("IFRAME");
  iframe.setAttribute("src", "ios-log:#iOS#" + log);
  document.documentElement.appendChild(iframe);
  iframe.parentNode.removeChild(iframe);
  iframe = null;    
};
console.debug = console.log;
console.info = console.log;
console.warn = console.log;
console.error = console.log;

次に、shouldStartLoadWithRequest関数を使用して、iOSアプリのUIWebViewDelegateでこのURLをキャッチする必要があります。

- (BOOL)webView:(UIWebView *)webView2 
shouldStartLoadWithRequest:(NSURLRequest *)request 
 navigationType:(UIWebViewNavigationType)navigationType {

    NSString *requestString = [[[request URL] absoluteString] stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
    //NSLog(requestString);

    if ([requestString hasPrefix:@"ios-log:"]) {
        NSString* logString = [[requestString componentsSeparatedByString:@":#iOS#"] objectAtIndex:1];
                               NSLog(@"UIWebView console: %@", logString);
        return NO;
    }

    return YES;
}
82
TinkerTank

今日、尊敬されている同僚と相談した後、Safari Developer Toolkit、およびコンソール出力(およびデバッグ!)のためにiOSシミュレーターでUIWebViewsに接続する方法について警告を受けました。

手順:

  1. Safariの設定を開きます-> [詳細設定]タブ-> [メニューバーに開発メニューを表示]チェックボックスを有効にします
  2. IOSシミュレーターのUIWebViewでアプリを起動します
  3. Safari->開発-> i(Pad/Pod) Simulator-> [the name of your UIWebView file]

これで、複雑な(私の場合はflot)Javascriptやその他のものをUIWebViewsにドロップして、自由にデバッグできます。

編集:@Joshua J McKinnonが指摘したように、この戦略はデバイス上でUIWebViewをデバッグするときにも機能します。デバイス設定でWeb Inspectorを有効にします。[設定]-> [Safari]-> [詳細設定]-> [Web Inspector](歓声@Jeremy Wiebe)

更新:WKWebViewもサポートされています

171
NSTJ

ここにSwift solution:(コンテキストを取得するためのちょっとしたハックです)

  1. UIWebViewを作成します。

  2. 内部コンテキストを取得し、console.log() javascript関数をオーバーライドします。

    self.webView = UIWebView()
    self.webView.delegate = self
    
    let context = self.webView.valueForKeyPath("documentView.webView.mainFrame.javaScriptContext") as! JSContext
    
    let logFunction : @convention(block) (String) -> Void =
    {
        (msg: String) in
    
        NSLog("Console: %@", msg)
    }
    context.objectForKeyedSubscript("console").setObject(unsafeBitCast(logFunction, AnyObject.self), 
                                                         forKeyedSubscript: "log")
    
34
Leslie Godwin

IOS7以降では、ネイティブJavascriptブリッジを使用できます。次のような単純なもの

 #import <JavaScriptCore/JavaScriptCore.h>

JSContext *ctx = [webview valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
ctx[@"console"][@"log"] = ^(JSValue * msg) {
NSLog(@"JavaScript %@ log message: %@", [JSContext currentContext], msg);
    };
28
Ji Fang

NativeBridgeは、UIWebViewからObjective-Cへの通信に非常に役立ちます。これを使用して、コンソールログを渡し、Objective-C関数を呼び出すことができます。

https://github.com/ochameau/NativeBridge

console = new Object();
console.log = function(log) {
    NativeBridge.call("logToConsole", [log]);
};
console.debug = console.log;
console.info = console.log;
console.warn = console.log;
console.error = console.log;

window.onerror = function(error, url, line) {
    console.log('ERROR: '+error+' URL:'+url+' L:'+line);
};

この手法の利点は、ログメッセージの改行などが保持されることです。

9
tangent405

レスリーゴッドウィンの修正を試みましたが、このエラーが発生していました。

'objectForKeyedSubscript' is unavailable: use subscripting

Swift 2.2の場合、次のように機能しました。

このコードをコンパイルするには、JavaScriptCoreをインポートする必要があります。

import JavaScriptCore

if let context = webView.valueForKeyPath("documentView.webView.mainFrame.javaScriptContext") {
    context.evaluateScript("var console = { log: function(message) { _consoleLog(message) } }")
    let consoleLog: @convention(block) String -> Void = { message in
        print("javascript_log: " + message)
    }
    context.setObject(unsafeBitCast(consoleLog, AnyObject.self), forKeyedSubscript: "_consoleLog")
}

次に、JavaScriptコードでconsole.log( "_ your_log_")を呼び出すと、Xcodeコンソールに出力されます。

さらに良いことに、このコードをUIWebViewの拡張機能として追加します。

import JavaScriptCore

extension UIWebView {
    public func hijackConsoleLog() {
        if let context = valueForKeyPath("documentView.webView.mainFrame.javaScriptContext") {
            context.evaluateScript("var console = { log: function(message) { _consoleLog(message) } }")
            let consoleLog: @convention(block) String -> Void = { message in
                print("javascript_log: " + message)
            }
            context.setObject(unsafeBitCast(consoleLog, AnyObject.self), forKeyedSubscript: "_consoleLog")
        }
    }
}

そして、UIWebView初期化ステップ中にこのメソッドを呼び出します:

let webView = UIWebView(frame: CGRectZero)
webView.hijackConsoleLog()
0
parag