Quando si scrive un'app per iPhone / iPad con UIWebView, la console non è visibile. questa eccellente risposta mostra come intercettare gli errori, ma vorrei usare anche console.log ().
Quando si scrive un'app per iPhone / iPad con UIWebView, la console non è visibile. questa eccellente risposta mostra come intercettare gli errori, ma vorrei usare anche console.log ().
Risposte:
Dopo essersi consultato con uno stimato collega oggi, mi ha avvisato del Safari Developer Toolkit e di come questo può essere collegato a UIWebViews nel simulatore iOS per l'output della console (e il debug!).
Passaggi:
[the name of your UIWebView file]
Ora puoi rilasciare Javascript complessi (nel mio caso, flot ) e altre cose in UIWebViews ed eseguire il debug a piacimento.
EDIT: come sottolineato da @Joshua J McKinnon, questa strategia funziona anche durante il debug di UIWebViews su un dispositivo. Abilita semplicemente Web Inspector nelle impostazioni del tuo dispositivo: Impostazioni-> Safari-> Avanzate-> Web Inspector (cheers @Jeremy Wiebe)
AGGIORNAMENTO: anche WKWebView è supportato
Ho una soluzione per accedere, utilizzando javascript, alla console di debug delle app. È un po 'rozzo, ma funziona.
Innanzitutto, definiamo la funzione console.log () in javascript, che apre e rimuove immediatamente 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;
Ora dobbiamo catturare questo URL in UIWebViewDelegate nell'app iOS usando la funzione 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;
}
Ecco la soluzione Swift: (È un po 'un trucco per ottenere il contesto)
Crei il UIWebView.
Ottieni il contesto interno e sovrascrivi la funzione 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
framework al tuo progetto e di import
inserirlo nel tuo file swift webview.
A partire da iOS7, puoi utilizzare il bridge Javascript nativo. Qualcosa di semplice come seguire
#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
, puoi configurare qualsiasi JSContext
cosa.
JSContext
ancora in iOS 8+ con WKWebView
?
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
e funziona perfettamente!
NativeBridge è molto utile per comunicare da un UIWebView a Objective-C. Puoi usarlo per passare i registri della console e chiamare le funzioni 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);
};
Il vantaggio di questa tecnica è che cose come le nuove righe nei messaggi di log vengono conservate.
console.log
, ma la window.onerror
funzione in questa risposta è molto utile!
Ho provato la correzione di Leslie Godwin ma ho ricevuto questo errore:
'objectForKeyedSubscript' is unavailable: use subscripting
Per Swift 2.2, ecco cosa ha funzionato per me:
Dovrai importare JavaScriptCore per compilare questo codice:
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")
}
Quindi nel tuo codice javascript, la chiamata a console.log ("_ your_log_") verrà stampata nella console Xcode.
Meglio ancora, aggiungi questo codice come estensione 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")
}
}
}
E quindi chiama questo metodo durante il passaggio di inizializzazione di UIWebView:
let webView = UIWebView(frame: CGRectZero)
webView.hijackConsoleLog()