iOS UIWebView中的Javascript console.log()

Tin*_*ank 80 javascript uiwebview ios

使用UIWebView编写iPhone/iPad应用程序时,控制台不可见. 这个优秀的答案显示了如何捕获错误,但我也想使用console.log().

NST*_*STJ 174

在咨询了一位受人尊敬的同事之后,他提醒我使用Safari Developer Toolkit,以及如何将其连接到iOS模拟器中的UIWebViews以进行控制台输出(以及调试!).

脚步:

  1. 打开Safari首选项 - >"高级"选项卡 - >启用复选框"在菜单栏中显示开发菜单"
  2. 在iOS模拟器中使用UIWebView启动应用程序
  3. Safari - >开发 - > i(Pad/Pod)模拟器 - > [the name of your UIWebView file]

您现在可以将复杂的(在我的情况下,flot)Javascript和其他内容放入UIWebViews并随意调试.

编辑:正如@Joshua J McKinnon所指出的,这种策略在设备上调试UIWebViews时也适用.只需在设备设置上启用Web Inspector:设置 - > Safari->高级 - > Web检查器(欢呼@Jeremy Wiebe)

更新:WKWebView也受支持

  • 注意,在真正的iOS设备上调试时,此策略也适用. (13认同)
  • @Floydian你必须在设备上启用Web Inspector.设置 - > Safari->高级 - > Web Inspector. (10认同)
  • 如果可以的话,+ 100.这很棒,它适用于手机间隙应用程序! (2认同)
  • 尝试使用iPad,当我进入Safari的开发菜单时,没有可供选择的设备.当我在模拟器上部署时,它就像一个魅力. (2认同)
  • 我的应用程序未显示在我的开发菜单中。我已启用Web检查器。出现了Safari,但是没有检测到我的应用程序(当前;正在显示2个UIWebviews)。 (2认同)

Tin*_*ank 82

我有一个使用javascript记录到apps调试控制台的解决方案.它有点粗糙,但它的工作原理.

首先,我们在javascript中定义console.log()函数,该函数打开并立即删除带有ios-log:url的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;
Run Code Online (Sandbox Code Playgroud)

现在我们必须使用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;
}
Run Code Online (Sandbox Code Playgroud)


Les*_*win 35

这是Swift解决方案:( 获取上下文有点破解)

  1. 您创建UIWebView.

  2. 获取内部上下文并覆盖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")
    
    Run Code Online (Sandbox Code Playgroud)

  • +100!救了我很多时间,很棒的黑客,需要对JS代码进行0次更改.谢谢!!对于未来的读者,我只需要2美分:不要忘记将"JavaScriptCore"框架链接到您的项目,并在webview swift文件中"导入"它. (3认同)

Ji *_*ang 28

从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);
    };
Run Code Online (Sandbox Code Playgroud)

  • `JSContext`是否仍然可以在iOS 8+中使用`WKWebView`? (4认同)

小智 9

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);
};
Run Code Online (Sandbox Code Playgroud)

这种技术的优点是保留了日志消息中的换行符.