it-swarm.com.de

Javascript console.log () in einer iOS-Benutzeroberfläche

Wenn Sie eine iPhone/iPad-App mit einem UIWebView schreiben, ist die Konsole nicht sichtbar diese ausgezeichnete Antwort zeigt, wie Fehler aufgefangen werden, aber ich möchte auch die console.log () verwenden.

76
TinkerTank

Ich habe eine Lösung, um mich mit Javascript an der Debug-Konsole für Apps anzumelden. Es ist etwas grob, aber es funktioniert.

Zuerst definieren wir die Funktion console.log () in Javascript, das einen iframe mit einem ios-log: url öffnet und sofort entfernt.

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

Jetzt müssen wir diese URL in UIWebViewDelegate in der iOS-App mithilfe der shouldStartLoadWithRequest-Funktion abrufen.

- (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;
}
81
TinkerTank

Nachdem ich mich heute mit einem geschätzten Kollegen beraten habe, hat er mich auf das Safari Developer Toolkit aufmerksam gemacht und wie diese Verbindung zu UIWebViews im iOS Simulator für die Konsolenausgabe (und das Debuggen!) Hergestellt werden kann.

Schritte:

  1. Öffnen Sie die Safari-Einstellungen -> Registerkarte "Erweitert" -> Aktivieren Sie das Kontrollkästchen "Entwicklungsmenü in der Menüleiste anzeigen".
  2. Starten Sie die App mit UIWebView im iOS-Simulator
  3. Safari -> Entwickeln -> i(Pad/Pod) Simulator -> [the name of your UIWebView file]

Sie können jetzt komplexe (in meinem Fall flot ) Javascript und andere Dinge in UIWebViews ablegen und nach Belieben debuggen.

BEARBEITEN: Wie von @Joshua J McKinnon ausgeführt, funktioniert diese Strategie auch beim Debuggen von UIWebViews auf einem Gerät. Aktivieren Sie einfach den Web Inspector in den Geräteeinstellungen: Einstellungen-> Safari-> Erweitert-> Web Inspector (cheers @Jeremy Wiebe)

UPDATE: WKWebView wird ebenfalls unterstützt

167
NSTJ

Hier ist die Swift-Lösung: (Es ist ein bisschen hack, um den Kontext zu verstehen)

  1. Sie erstellen die UIWebView. 

  2. Rufen Sie den internen Kontext ab und überschreiben Sie die Funktionconsole.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")
    
32
Leslie Godwin

Ab iOS7 können Sie native Javascript-Bridge verwenden. Etwas so einfaches wie folgt

 #import <JavaScriptCore/JavaScriptCore.h>

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

NativeBridge ist sehr hilfreich für die Kommunikation von UIWebView zu Objective-C. Sie können es verwenden, um Konsolenprotokolle zu übergeben und Objective-C-Funktionen aufzurufen.

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

Der Vorteil dieser Technik besteht darin, dass beispielsweise Nachrichten in Protokollnachrichten erhalten bleiben.

9
tangent405

Versuchte Leslie Godwins Fehlerbehebung, erhielt jedoch diesen Fehler:

'objectForKeyedSubscript' is unavailable: use subscripting

Für Swift 2.2 hat sich Folgendes bewährt:

Sie müssen JavaScriptCore importieren, damit dieser Code kompiliert werden kann:

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

Anschließend wird in Ihrem Javascript-Code der Aufruf von console.log ("_ your_log_") in der Xcode-Konsole gedruckt.

Besser noch, fügen Sie diesen Code als Erweiterung zu UIWebView hinzu:

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

Rufen Sie dann diese Methode während Ihres UIWebView-Initialisierungsschritts auf:

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