Pregunta Javascript console.log () en una UIWebView de iOS


Al escribir una aplicación para iPhone / iPad con UIWebView, la consola no está visible. esta excelente respuesta muestra cómo atrapar errores, pero también me gustaría usar console.log ().


74
2018-06-28 14:43


origen


Respuestas:


Después de consultar con un colega estimado hoy, me alertó sobre Safari Developer Toolkit, y cómo esto se puede conectar a UIWebViews en el simulador de iOS para la salida de la consola (¡y depuración!).

Pasos:

  1. Abra Preferencias de Safari -> pestaña "Avanzado" -> active la casilla de verificación "Mostrar el menú de Desarrollo en la barra de menú"
  2. Inicie la aplicación con UIWebView en iOS Simulator
  3. Safari -> Desarrollar -> i (Pad / Pod) Simulador -> [the name of your UIWebView file]

Ahora puede eliminar complejos (en mi caso, flotante) Javascript y otras cosas en UIWebViews y depuración a voluntad.

EDITAR: Como señaló @Joshua J McKinnon, esta estrategia también funciona al depurar UIWebViews en un dispositivo. Simplemente habilite Web Inspector en la configuración de su dispositivo: Configuración-> Safari-> Avanzado-> Web Inspector (vítores @Jeremy Wiebe)

ACTUALIZACIÓN: WKWebView es compatible también


149
2017-11-27 02:56



Tengo una solución para iniciar sesión, usando javascript, en la consola de depuración de aplicaciones. Es un poco crudo, pero funciona.

Primero, definimos la función console.log () en javascript, que se abre e inmediatamente elimina un iframe con un ios-log: url.

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

Ahora tenemos que atrapar esta URL en UIWebViewDelegate en la aplicación iOS utilizando la función shouldStartLoadWithRequest.

- (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
2018-06-28 14:45



Aquí está la solución Swift: (Es un poco complicado para entender el contexto)

  1. Usted crea el UIWebView.

  2. Obtenga el contexto interno y anule el console.log () función 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")
    

30
2017-11-17 08:08



A partir de iOS7, puede usar el puente Javascript nativo. Algo tan simple como seguir

 #import <JavaScriptCore/JavaScriptCore.h>

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

24
2018-02-15 19:47



NativeBridge es muy útil para comunicarse desde un UIWebView a Objective-C. Puede usarlo para pasar los registros de la consola y llamar a las funciones de 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);
};

La ventaja de esta técnica es que se preservan cosas como las nuevas líneas en los mensajes de registro.


8
2018-02-14 20:37



Intenté la solución de Leslie Godwin pero estaba obteniendo este error:

'objectForKeyedSubscript' is unavailable: use subscripting

Para Swift 2.2, esto es lo que funcionó para mí:

Necesitará importar JavaScriptCore para compilar este código:

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

Luego, en su código de JavaScript, la llamada a console.log ("_ your_log_") se imprimirá en la consola de Xcode.

Mejor aún, agregue este código como una extensión de 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")
        }
    }
}

Y luego llame a este método durante su paso de inicialización de UIWebView:

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

0
2017-07-08 21:36