获取来自 WKWebView 的 JavaScript 错误

Posted

技术标签:

【中文标题】获取来自 WKWebView 的 JavaScript 错误【英文标题】:Get JavaScript errors coming from WKWebView 【发布时间】:2016-06-01 09:31:29 【问题描述】:

我实现了WKScriptMessageHandler 协议并定义了userContentController(:didReceiveScriptMessage:) 方法。

javascript 出现错误时,我会(在 WKScriptMessage 对象中)得到一些不太有用的东西,例如:


    col = 0;
    file = "";
    line = 0;
    message = "Script error.";
    type = error;

另一方面,如果我打开 Safari Web Inspector,我可以看到真正的错误(例如):

TypeError: FW.Ui.Modal.sho is not a function. (In 'FW.Ui.Modal.sho', 'FW.Ui.Modal.sho' is undefined)

有没有办法在我的本机代码中恢复该错误?

编辑: 澄清一下,javascript 代码是由 javascript 开发人员编写的(他无权访问本机源代码,因此无法通过 Xcode 调试应用程序)。然后将他编写的代码推送到 ios 应用(从企业应用商店下载)。

【问题讨论】:

【参考方案1】:

您可以在计算之前将表达式包装在 try catch 块中。然后让 JavaScript 在失败时返回错误消息。以下是来自Turbolinks-iOS adapter 的示例,可在 GitHub 上找到。

extension WKWebView 
   func callJavaScriptFunction(functionExpression: String, withArguments arguments: [AnyObject?] = [], completionHandler: ((AnyObject?) -> ())? = nil) 
        guard let script = scriptForCallingJavaScriptFunction(functionExpression, withArguments: arguments) else 
            NSLog("Error encoding arguments for JavaScript function `%@'", functionExpression)
            return
        

        evaluateJavaScript(script)  (result, error) in
            if let result = result as? [String: AnyObject] 
                if let error = result["error"] as? String, stack = result["stack"] as? String 
                    NSLog("Error evaluating JavaScript function `%@': %@\n%@", functionExpression, error, stack)
                 else 
                    completionHandler?(result["value"])
                
             else if let error = error 
                self.delegate?.webView(self, didFailJavaScriptEvaluationWithError: error)
            
        
    

    private func scriptForCallingJavaScriptFunction(functionExpression: String, withArguments arguments: [AnyObject?]) -> String? 
        guard let encodedArguments = encodeJavaScriptArguments(arguments) else  return nil 

        return
            "(function(result) \n" +
            "  try \n" +
            "    result.value = " + functionExpression + "(" + encodedArguments + ")\n" +
            "   catch (error) \n" +
            "    result.error = error.toString()\n" +
            "    result.stack = error.stack\n" +
            "  \n" +
            "  return result\n" +
            ")()"
    

    private func encodeJavaScriptArguments(arguments: [AnyObject?]) -> String? 
        let arguments = arguments.map  $0 == nil ? NSNull() : $0! 

        if let data = try? NSJSONSerialization.dataWithJSONObject(arguments, options: []),
            string = NSString(data: data, encoding: NSUTF8StringEncoding) as? String 
                return string[string.startIndex.successor() ..< string.endIndex.predecessor()]
        

        return nil
    

【讨论】:

如果我理解正确,这个解决方案在我的场景中不起作用,其中有一个 javascript 开发人员在自己的计算机上编写代码,然后这个代码被推送到 iOS 应用程序(例如从企业应用商店)。 JS 开发人员将无法看到正确的错误(上例中的语法错误),而只是一般的“脚本错误”。我说的对吗? 啊,明白了。您是对的,此代码用于评估嵌入在 iOS 客户端中的脚本。但是,同样的 try catch 心态也适用 - 只需在开发脚本时实现该代码。 如果代码很小,它可能会起作用。但如果代码是数千行代码,我猜你不能把所有东西都放在try catch 中。此外,我不确定try catch 是否适用于我的问题中的语法错误:try result.sho(); catch (error) ... ;

以上是关于获取来自 WKWebView 的 JavaScript 错误的主要内容,如果未能解决你的问题,请参考以下文章

来自 WKWebview 的 iCLoud 文档选择器关闭容器视图

设置 AVAudioSession 类别对来自 WKWebView 的声音没有影响

WKWebView 在 safari 中打开来自某个域的链接

IOS - 来自本地HTML文件的WKWebView中的CORS

来自html字符串的iOS Swift 4图像未在WKWebView中加载

来自钥匙串的 Swift 4 WKWebView 身份验证