動かない - iOS UIWebViewのJavascript console.log()




uiwebviewとは 非推奨 (6)

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

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


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

このテクニックの利点は、ログメッセージの改行のようなものが保存されることです。


敬具を付けられた同僚と相談した後、彼はSafari Developer Toolkitと、これをiOS Simulatorのコンソール出力(およびデバッグ)用UIWebViewsにどのように関連付けることができるかを警告しました。

ステップ:

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

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

編集:@ジョシュアJマッキノンによって指摘されるように、この戦略は、デバイス上でUIWebViewsをデバッグするときにも機能します。 あなたのデバイス設定でWeb Inspectorを有効にするだけです:Settings-> Safari-> Advanced-> Web Inspector(歓声@Jeremy Wiebe)

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


私は、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;
}

試したレスリー・ゴッドウィンの修正だが、このエラーが出ていた:

'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()

これはSwiftを使用したソリューションです。

import UIKit

class ExampleViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var scrollView: UIScrollView!

    @IBOutlet var textField1: UITextField!
    @IBOutlet var textField2: UITextField!
    @IBOutlet var textField3: UITextField!
    @IBOutlet var textField4: UITextField!
    @IBOutlet var textField5: UITextField!

    var activeTextField: UITextField!

    // MARK: - View
    override func viewDidLoad() {
        super.viewDidLoad()
        self.textField1.delegate = self
        self.textField2.delegate = self
        self.textField3.delegate = self
        self.textField4.delegate = self
        self.textField5.delegate = self
    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        self.registerForKeyboardNotifications()
    }

    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)
        self.unregisterFromKeyboardNotifications()
    }

    // MARK: - Keyboard

    // Call this method somewhere in your view controller setup code.
    func registerForKeyboardNotifications() {
        let center:  NSNotificationCenter = NSNotificationCenter.defaultCenter()
        center.addObserver(self, selector: "keyboardWasShown:", name: UIKeyboardDidShowNotification, object: nil)
        center.addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil)
    }

    func unregisterFromKeyboardNotifications () {
        let center:  NSNotificationCenter = NSNotificationCenter.defaultCenter()
        center.removeObserver(self, name: UIKeyboardDidShowNotification, object: nil)
        center.removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
    }

    // Called when the UIKeyboardDidShowNotification is sent.
    func keyboardWasShown (notification: NSNotification) {
        let info : NSDictionary = notification.userInfo!
        let kbSize = (info.objectForKey(UIKeyboardFrameBeginUserInfoKey)?.CGRectValue() as CGRect!).size

        let contentInsets: UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
        scrollView.contentInset = contentInsets;
        scrollView.scrollIndicatorInsets = contentInsets;

        // If active text field is hidden by keyboard, scroll it so it's visible
        // Your app might not need or want this behavior.
        var aRect = self.view.frame
        aRect.size.height -= kbSize.height;
        if (!CGRectContainsPoint(aRect, self.activeTextField.frame.origin) ) {
            self.scrollView.scrollRectToVisible(self.activeTextField.frame, animated: true)
        }
    }

    // Called when the UIKeyboardWillHideNotification is sent
    func keyboardWillBeHidden (notification: NSNotification) {
        let contentInsets = UIEdgeInsetsZero;
        scrollView.contentInset = contentInsets;
        scrollView.scrollIndicatorInsets = contentInsets;
    }

    // MARK: -  Text Field

    func textFieldDidBeginEditing(textField: UITextField) {
        self.activeTextField = textField
    }

    func textFieldDidEndEditing(textField: UITextField) {
        self.activeTextField = nil
    }

}




javascript ios uiwebview