Beim Schreiben einer iPhone / iPad-App mit einer UIWebView ist die Konsole nicht sichtbar. Diese ausgezeichnete Antwort zeigt, wie man Fehler abfängt, aber ich möchte auch die console.log () verwenden.
Beim Schreiben einer iPhone / iPad-App mit einer UIWebView ist die Konsole nicht sichtbar. Diese ausgezeichnete Antwort zeigt, wie man Fehler abfängt, aber ich möchte auch die console.log () verwenden.
Antworten:
Nachdem er sich heute mit einem geschätzten Kollegen beraten hatte, machte er mich auf das Safari Developer Toolkit aufmerksam und darauf, wie dieses mit UIWebViews im iOS-Simulator für die Konsolenausgabe (und das Debuggen!) Verbunden werden kann.
Schritte:
[the name of your UIWebView file]
Sie können jetzt komplexes (in meinem Fall flot ) Javascript und andere Dinge in UIWebViews ablegen und nach Belieben debuggen.
BEARBEITEN: Wie von @Joshua J McKinnon hervorgehoben, funktioniert diese Strategie auch beim Debuggen von UIWebViews auf einem Gerät. Aktivieren Sie einfach den Web Inspector in Ihren Geräteeinstellungen: Einstellungen-> Safari-> Erweitert-> Web Inspector (Prost @Jeremy Wiebe)
UPDATE: WKWebView wird ebenfalls unterstützt
Ich habe eine Lösung, um mich mit Javascript bei der Apps-Debug-Konsole anzumelden. Es ist ein bisschen grob, aber es funktioniert.
Zuerst definieren wir die Funktion console.log () in Javascript, die einen Iframe mit einer 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 im UIWebViewDelegate in der iOS-App mit der Funktion shouldStartLoadWithRequest abfangen.
- (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;
}
Hier ist die Swift-Lösung: (Es ist ein kleiner Hack, den Kontext zu ermitteln.)
Sie erstellen die UIWebView.
Rufen Sie den internen Kontext ab und überschreiben Sie die Javascript-Funktion 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 mit Ihrem Projekt und import
seiner Webview-Swift-Datei zu verknüpfen .
Ab iOS7 können Sie die native Javascript-Brücke verwenden. Etwas so Einfaches wie das Folgende
#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
, können Sie alles JSContext
einrichten.
JSContext
noch in iOS 8+ mit WKWebView
?
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
und es funktioniert perfekt!
WKWebView
und iOS 11.4.1 versucht und er kann nicht finden documentView
und stürzt ab. Ich habe diese Antwort gesehen und es scheint, dass dies nicht möglich ist.
NativeBridge ist sehr hilfreich für die Kommunikation von einer UIWebView zu Objective-C. Sie können damit Konsolenprotokolle übergeben und Objective-C-Funktionen aufrufen.
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 Zeilenumbrüche in Protokollnachrichten beibehalten werden.
console.log
, aber die window.onerror
Funktion in dieser Antwort ist sehr nützlich!
Versuchte Leslie Godwins Lösung, bekam aber diesen Fehler:
'objectForKeyedSubscript' is unavailable: use subscripting
Für Swift 2.2 hat Folgendes für mich funktioniert:
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")
}
Wenn Sie dann in Ihrem Javascript-Code console.log ("_ your_log_") aufrufen, wird 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 diese Methode dann während Ihres UIWebView-Initialisierungsschritts auf:
let webView = UIWebView(frame: CGRectZero)
webView.hijackConsoleLog()