iOS UIWebView 中的 Javascript console.log()

IT技术 javascript ios uiwebview
2021-03-02 03:54:12

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

6个回答

今天咨询了一位受人尊敬的同事后,他提醒我注意 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 Inspector(干杯 @Jeremy Wiebe)

更新:也支持 WKWebView

尝试使用 iPad,当我转到 Safari 上的开发菜单时,没有设备可供选择。当我在模拟器上部署时,它就像一个魅力。
2021-04-20 03:54:12
我的应用程序没有出现在我的开发菜单中。我启用了网络检查器。Safari 出现了,但没有检测到我的应用程序(当前的;显示 2 个 UIWebviews)。有什么想法吗?
2021-04-28 03:54:12
@Floydian 您必须在设备上启用 Web Inspector。设置->Safari->高级->Web Inspector。
2021-05-02 03:54:12
如果可以的话,+100。这太棒了,它也适用于电话间隙应用程序!
2021-05-04 03:54:12
请注意,此策略也适用于在真实 iOS 设备上进行调试。
2021-05-11 03:54:12

我有一个使用 javascript 登录到应用程序调试控制台的解决方案。这有点粗糙,但它有效。

首先,我们在 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;

现在我们必须使用 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;
}
请参阅下面的 NSTJ 的简单想法。
2021-04-23 03:54:12
在 swift 4 也许?:D
2021-05-15 03:54:12

这是 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")
    
使用 Swift 4 对我有用......你必须将“log”转换为 NSString..context.objectForKeyedSubscript("console").setObject(unsafeBitCast(logFunction, to: AnyObject.self), forKeyedSubscript: "log" as NSString)
2021-04-22 03:54:12
+100!为我节省了大量时间,很棒的 hack,需要对 JS 代码进行 0 次更改。谢谢!!对于未来的读者,我只需 2 美分:不要忘记将JavaScriptCore框架链接到您的项目,并将import链接到您的 webview swift 文件中。
2021-04-26 03:54:12

从 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);
    };
是否JSContext在iOS中仍然工作8+用WKWebView
2021-04-17 03:54:12
出于兴趣,放置此代码的理想位置在哪里?
2021-04-18 03:54:12
我把它放进去- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType,效果很好!
2021-04-28 03:54:12
好的,想通了。在创建之后,UIWebview您可以设置任何JSContext东西。
2021-05-02 03:54:12
@NikolaiSamteladze:我尝试使用WKWebViewiOS 11.4.1,但他找不到documentView并崩溃了。我看到了这个答案,似乎不可能这样。
2021-05-09 03:54:12

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);
};

这种技术的优点是保留了日志消息中的换行符之类的内容。

对于 Appcelerator/Titanium 开发人员:这也适用于调试您的 Ti.UI.WebView
2021-05-03 03:54:12
+1。请注意Apache Cordova用户 - Cordova 已经处理了console.log,但是window.onerror此答案中功能非常有用!
2021-05-04 03:54:12