Lors de l'écriture d'une application iPhone/iPad avec UIWebView, la console n'est pas visible . cette excellente réponse montre comment intercepter les erreurs, mais j'aimerais également utiliser console.log ().
J'ai une solution pour vous connecter, en utilisant javascript, à la console de débogage des applications . C'est un peu brut, mais ça fonctionne.
Premièrement, nous définissons la fonction console.log () en javascript, qui ouvre et supprime immédiatement un iframe avec 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;
Nous devons maintenant intercepter cette URL dans UIWebViewDelegate dans l'application iOS à l'aide de la fonction 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;
}
Après avoir consulté un collègue estimé aujourd'hui, il m'a alerté sur Safari Developer Toolkit et sur la manière de le connecter à UIWebViews dans le simulateur iOS pour une sortie de console (et le débogage!).
Pas:
[the name of your UIWebView file]
Vous pouvez maintenant déposer du code Javascript complexe (dans mon cas, flot ) dans UIWebViews et le déboguer à volonté.
EDIT: Comme l'a souligné @Joshua J McKinnon, cette stratégie fonctionne également lors du débogage de UIWebViews sur un périphérique. Activez simplement Web Inspector sur les paramètres de votre appareil: Paramètres-> Safari-> Avancé-> Web Inspector (acclamations @Jeremy Wiebe)
UPDATE: WKWebView est également pris en charge
À partir de iOS7, vous pouvez utiliser le pont Javascript natif. Quelque chose d'aussi simple que de suivre
#import <JavaScriptCore/JavaScriptCore.h>
JSContext *ctx = [webview valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
ctx[@"console"][@"log"] = ^(JSValue * msg) {
NSLog(@"JavaScript %@ log message: %@", [JSContext currentContext], msg);
};
NativeBridge est très utile pour communiquer d'un UIWebView à Objective-C. Vous pouvez l'utiliser pour passer les journaux de la console et appeler des fonctions 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);
};
L'avantage de cette technique est que des éléments tels que les nouvelles lignes dans les messages de journal sont préservés.
Essayé le correctif de Leslie Godwin, mais obtenait cette erreur:
'objectForKeyedSubscript' is unavailable: use subscripting
Pour Swift 2.2, voici ce qui a fonctionné pour moi:
Vous devrez importer JavaScriptCore pour que ce code soit compilé:
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")
}
Ensuite, dans votre code javascript, l'appel de console.log ("_ your_log_") sera imprimé dans la console Xcode.
Mieux encore, ajoutez ce code en tant qu’extension 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")
}
}
}
Et appelez ensuite cette méthode lors de votre étape d'initialisation de UIWebView:
let webView = UIWebView(frame: CGRectZero)
webView.hijackConsoleLog()