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 ().
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 ().
Respuestas:
Después de consultar con un estimado colega 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 la depuración!).
Pasos:
[the name of your UIWebView file]
Ahora puede colocar Javascript complejo (en mi caso, flot ) y otras cosas en UIWebViews y depurar a voluntad.
EDITAR: Como lo 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 (salud @Jeremy Wiebe)
ACTUALIZACIÓN: WKWebView también es compatible
Tengo una solución para iniciar sesión, usando javascript, en la consola de depuración de aplicaciones. Es un poco tosco, pero funciona.
Primero, definimos la función console.log () en javascript, que abre y elimina inmediatamente 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 capturar esta URL en UIWebViewDelegate en la aplicación de iOS usando 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;
}
Aquí está la solución Swift: (es un truco para obtener el contexto)
Creas el UIWebView.
Obtenga el contexto interno y anule la función de JavaScript console.log () .
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")
JavaScriptCore
marco a su proyecto y import
en su archivo rápido de webview.
A partir de iOS7, puede utilizar 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);
};
UIWebview
, puede configurar cualquier elemento JSContext
.
JSContext
Sigue funcionando en iOS 8+ con WKWebView
?
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
y funciona perfectamente!
NativeBridge es muy útil para comunicarse desde UIWebView a Objective-C. Puede usarlo para pasar registros de la consola y llamar a 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 conservan elementos como las líneas nuevas en los mensajes de registro.
console.log
, ¡pero la window.onerror
función en esta respuesta es muy útil!
Probé la solución de Leslie Godwin pero recibí este error:
'objectForKeyedSubscript' is unavailable: use subscripting
Para Swift 2.2, esto es lo que funcionó para mí:
Necesitará importar JavaScriptCore para que este código se compile:
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 javascript, al llamar a console.log ("_ your_log_") se imprimirá en la consola de Xcode.
Mejor aún, agregue este código como una extensión a 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 el paso de inicialización de UIWebView:
let webView = UIWebView(frame: CGRectZero)
webView.hijackConsoleLog()