Podczas pisania aplikacji na iPhone'a / iPada za pomocą UIWebView konsola nie jest widoczna. ta doskonała odpowiedź pokazuje, jak wychwytywać błędy, ale chciałbym również użyć console.log ().
Podczas pisania aplikacji na iPhone'a / iPada za pomocą UIWebView konsola nie jest widoczna. ta doskonała odpowiedź pokazuje, jak wychwytywać błędy, ale chciałbym również użyć console.log ().
Odpowiedzi:
Po dzisiejszej konsultacji z cenionym kolegą, poinformował mnie o Safari Developer Toolkit i o tym, jak można to połączyć z UIWebViews w symulatorze iOS w celu uzyskania danych wyjściowych z konsoli (i debugowania!).
Kroki:
[the name of your UIWebView file]
Możesz teraz upuszczać złożony (w moim przypadku flot ) JavaScript i inne rzeczy do UIWebViews i debugować do woli.
EDYCJA: Jak wskazał @Joshua J McKinnon, ta strategia działa również podczas debugowania UIWebViews na urządzeniu. Po prostu włącz Web Inspector w ustawieniach swojego urządzenia: Settings-> Safari-> Advanced-> Web Inspector (cheers @Jeremy Wiebe)
UPDATE: WKWebView jest również obsługiwany
Mam rozwiązanie do logowania za pomocą javascript do konsoli debugowania aplikacji. To trochę prymitywne, ale działa.
Najpierw definiujemy funkcję console.log () w javascript, która otwiera i natychmiast usuwa ramkę iframe z 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;
Teraz musimy przechwycić ten adres URL w UIWebViewDelegate w aplikacji iOS za pomocą funkcji 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;
}
Oto rozwiązanie Swift: (trochę hackowania, aby uzyskać kontekst)
Tworzysz UIWebView.
Pobierz kontekst wewnętrzny i nadpisz funkcję 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
frameworka ze swoim projektem i import
go w swoim pliku swift z przeglądarką internetową.
Począwszy od iOS7, możesz używać natywnego mostka JavaScript. Coś tak prostego, jak śledzenie
#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
możesz skonfigurować dowolne JSContext
rzeczy.
JSContext
nadal działa w iOS 8+ z WKWebView
?
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
i działa idealnie!
WKWebView
iOS 11.4.1 i iOS, ale nie może znaleźć documentView
i ulega awarii. Widziałem tę odpowiedź i wydaje się, że nie jest to możliwe w ten sposób.
NativeBridge jest bardzo pomocny w komunikacji z UIWebView do Objective-C. Możesz go użyć do przekazywania dzienników konsoli i wywoływania funkcji 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);
};
Zaletą tej techniki jest to, że zachowywane są takie elementy, jak znaki nowego wiersza w komunikatach dziennika.
console.log
, ale window.onerror
funkcja w tej odpowiedzi jest bardzo przydatna!
Wypróbowałem rozwiązanie Leslie Godwin, ale otrzymywałem ten błąd:
'objectForKeyedSubscript' is unavailable: use subscripting
W przypadku Swift 2.2, oto co zadziałało:
Aby skompilować ten kod, musisz zaimportować JavaScriptCore:
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")
}
Następnie w kodzie javascript wywołanie console.log ("_ twój_log_") zostanie wydrukowane w konsoli Xcode.
Jeszcze lepiej, dodaj ten kod jako rozszerzenie do 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")
}
}
}
A następnie wywołaj tę metodę podczas kroku inicjalizacji UIWebView:
let webView = UIWebView(frame: CGRectZero)
webView.hijackConsoleLog()