使用UIWebView编写iPhone / iPad应用程序时,控制台不可见。 这个极好的答案显示了如何捕获错误,但是我也想使用console.log()。
Answers:
在咨询了一位尊敬的同事之后,他提醒我使用Safari开发者工具包,以及如何将其连接到iOS模拟器中的UIWebViews进行控制台输出(和调试!)。
脚步:
[the name of your UIWebView file]
您现在可以将复杂的Javascript和其他内容(在我的情况下为flot)放到UIWebViews中,然后随意进行调试。
编辑:正如@Joshua J McKinnon所指出的,该策略在设备上调试UIWebViews时也适用。只需在设备设置上启用Web Inspector:设置-> Safari->高级-> Web Inspector(欢呼@Jeremy Wiebe)
更新:WKWebView也受支持
我有一个解决方案,可以使用JavaScript登录到应用程序调试控制台。有点粗糙,但是可以用。
首先,我们在javascript中定义console.log()函数,该函数将打开并立即删除带有ios-log:网址的iframe。
// 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;
现在,我们必须使用shouldStartLoadWithRequest函数在iOS应用程序的UIWebViewDelegate中捕获此URL。
- (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;
}
这是Swift解决方案:( 获取上下文有点技巧)
您创建UIWebView。
获取内部上下文并覆盖console.log() javascript函数。
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
框架链接到您的项目,并将import
其链接到webview swift文件中。
从iOS7开始,您可以使用本机Javascript桥。如下简单
#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
您可以设置任何JSContext
东西。
JSContext
在iOS中仍然工作8+用WKWebView
?
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
,效果很好!
NativeBridge对于从UIWebView到Objective-C的通信非常有帮助。您可以使用它来传递控制台日志并调用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);
};
此技术的优点是保留了日志消息中的换行符之类的内容。
尝试了莱斯利·戈德温的修复方法,但遇到此错误:
'objectForKeyedSubscript' is unavailable: use subscripting
对于Swift 2.2,这对我有用:
您将需要导入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")
}
然后在您的JavaScript代码中,调用console.log(“ _ your_log_”)将在Xcode控制台中打印。
更好的是,将此代码添加为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")
}
}
}
然后在您的UIWebView初始化步骤中调用此方法:
let webView = UIWebView(frame: CGRectZero)
webView.hijackConsoleLog()