iOSUIWebViewのJavascriptconsole.log()


84

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


1
最初にブラウザに書き込み、開発ツールをオンにしてから、コンソール出力を確認します。
beatgammit 2011年

回答:


183

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

手順:

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

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

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

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


13
この戦略は、実際のiOSデバイスでデバッグする場合にも機能することに注意してください。
Joshua J. McKinnon 2013年

2
できれば+100。これは素晴らしいです、それは電話ギャップアプリでも機能します!
Andy Novocin 2014

2
iPadで試してみると、Safariの開発メニューに移動すると、選択するデバイスがありません。シミュレーターにデプロイすると、それは魅力のように機能します。
フロイディアン2014年

10
@FloydianデバイスでWebInspectorを有効にする必要があります。[設定]-> [Safari]-> [詳細]-> [Webインスペクター]。
Jeremy Wiebe 2014年

2
アプリが開発メニューに表示されません。Webインスペクターを有効にしました。Safariが表示されますが、私のアプリ(現在、2つのUIWebviewを表示しています)が検出されません。何かアイデアはありますか?
narco 2015

83

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;
}

1
以下のNSTJの簡単なアイデアを参照してください。
Ashwin S

迅速な4で多分?:D
Konstantinos Natsios 2018年

35

Swiftソリューションは次のとおりです:( コンテキストを取得するのは少しハックです)

  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")
    

3
+100!時間を大幅に節約できました。すばらしいハックで、JSコードを0回変更する必要があります。ありがとう!将来の読者のためにちょうど私の2セント:JavaScriptCoreフレームワークをあなたのプロジェクトとimportあなたのwebviewswiftファイルにリンクすることを忘れないでください。
マインドボム2015

Swift 4で動作します...「log」をNSString..context.objectForKeyedSubscript( "console")。setObject(unsafeBitCast(logFunction、to:AnyObject.self)、forKeyedSubscript: "log" as NSString)にキャストする必要があります
サージ

28

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);
    };

興味深いことに、このコードを配置する理想的な場所はどこですか?
レスリーゴッドウィン

OK、それを理解しました。作成した直後に、UIWebviewあらゆるJSContextものをセットアップできます。
レスリーゴッドウィン

4
JSContextiOS 8以降でも引き続き機能しWKWebViewますか?
Nikolai Samteladze 2016年

私はそれを入れて- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType、それは完璧に機能します!
Artur Bartczak 2016年

@NikolaiSamteladze:WKWebViewiOS 11.4.1で試してみましたが、彼は見つからずdocumentView、クラッシュします。私はこの答えを見ました、そしてそれはこの方法では不可能であるようです。
テスト

10

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);
};

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


+1。Apache Cordovaユーザーへの注意-Cordovaはすでに処理していますconsole.logが、window.onerrorこの回答の関数は非常に便利です!
mpontillo 2013

Appcelerator / Titanium開発者の場合:これもTi.UI.WebViewのデバッグに機能します
Byters

0

Leslie Godwinの修正を試しましたが、次のエラーが発生していました。

'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

スウィフト5

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
      webView.evaluateJavaScript("your javascript string") { (value, error) in
          if let errorMessage = (error! as NSError).userInfo["WKJavaScriptExceptionMessage"] as? String {
                print(errorMessage)
          }
      }
 }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.