WKWebView 中的链接随机不可点击

Posted

技术标签:

【中文标题】WKWebView 中的链接随机不可点击【英文标题】:Links in WKWebView randomly not clickable 【发布时间】:2016-01-09 12:12:50 【问题描述】:

在我用 Swift 2.1 编写的 ios 应用程序中,我使用 WKWebView 加载 html 字符串,该字符串是使用 JSON 解析器从 wordpress 博客加载的。

我实现了委托方法 func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) 并将 WKWebView 的导航委托设置为 self 以处理链接按下。

现在,当我打开包含 WKWebView 的 ViewController 时,此委托方法被调用一次,这是您在加载 webView 时所期望的行为 - 所以委托似乎设置正确。

我现在的问题是大多数时候 webView 包含的链接不可点击。您通常会期望当您按下一个链接时会出现灰色背景,如下图所示。但大多数时候,当我点击一个链接时,灰色背景不会出现,所以当我触摸时,委托方法不会被调用。这个问题当然与WKNavigationDelegate 的错误配置无关,因为有时链接选择可以正常工作(大约 10 %)。

您知道为什么随机链接有时不可点击,有时可点击(10% 的情况)?


【问题讨论】:

如果您能向我们展示您的 html,那就太好了。 忘记importing QuartzCore了吗? 【参考方案1】:

我假设您想要的是在某个地方有一些描述或文本,并允许在文本的某些部分内进行点击/点击,您想要使用 WKWebView

我在很久以前做的一些应用程序中也使用WKWebView解决了这个问题,当然有几个解决方案,它只是其中一个,没有别的。

正如某些人对您所说,您可以使用loadHTMLString 函数以 JSON 格式或您想要的任何方式从您的服务器加载 HTML 字符串,但非常重要的是 HTML 格式正确且没有错误。

关于loadHTMLString 函数的一个非常重要的一点是关于您的评论...您通常会期望当您按下链接时会出现灰色背景,如下图所示,如果 HTML 没有某种 CSS 样式,则不会发生这种情况,因为如果没有,它具有任何 <a><\a> 的默认样式。

那么让我们看看下面的代码:

import UIKit
import WebKit

class ViewController: UIViewController, WKNavigationDelegate 

   var wkWebView: WKWebView!

   override func viewDidLoad() 
       super.viewDidLoad()

       // The part of the HTMl you want to show
       let description = "Let's start to visit the <a href=\"http://www.apple.com/\">Apple</a> website first and then if you want the <a href=\"http://www.w3schools.com\">Developer Apple</a> website."


       // The default HTML with body and styles formatted and the description inside using string interpolation.
       let htmlString = "<html><head><style type=\"text/css\">body font-family: \"Lato-Regular\";font-size: 35px;color: #333333;margin: 0;a text-decoration: none; color: #999;</style></head><body>\(description)</body></html>"

       let preferences = WKPreferences()
       preferences.javascriptEnabled = false

       // Configuration for any preferences you want to set
       let configuration = WKWebViewConfiguration()
       configuration.preferences = preferences

       wkWebView = WKWebView(frame: CGRectMake(5, 35, self.view.bounds.width, self.view.bounds.height), configuration: configuration)

       if let theWebView = wkWebView 
          theWebView.loadHTMLString(htmlString, baseURL: NSURL())
          theWebView.navigationDelegate = self
          self.view.addSubview(theWebView)
       
   

   override func didReceiveMemoryWarning() 
      super.didReceiveMemoryWarning()
      // Dispose of any resources that can be recreated.
   

   func webView(webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) 
      UIApplication.sharedApplication().networkActivityIndicatorVisible = true
   


   func webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) 
      UIApplication.sharedApplication().networkActivityIndicatorVisible = false
   

   func webView(webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: NSError) 
     let alert = UIAlertController(title: "Error", message: error.localizedDescription, preferredStyle: .Alert)
     alert.addAction(UIAlertAction(title: "Ok", style: .Default)  (UIAlertAction) -> Void in
         UIApplication.sharedApplication().networkActivityIndicatorVisible = false
     )

     presentViewController(alert, animated: true, completion: nil)
   

在上面的代码中,我设置了变量description,其中包含一些带有可点击元素的文本,并添加了两个委托方法didStartProvisionalNavigationdidFinishNavigation 在状态栏中显示networkActivityIndicatorVisible 以显示一些进度关于点击可点击文本时页面的加载。很高兴注意到在htmlString 变量中我设置了一些样式来显示&lt;a&gt; 的一些颜色和字体,这取决于你。

我还添加了didFailProvisionalNavigation 函数以在某些情况下显示警报,URL 无效,例如添加的新HTTPTransportSecurityLayer 是iOS 9 仅允许https,在某些情况下您可以使用它来验证 url 并了解错误原因。

结果是普通UIViewController中的以下文本:

当你点击任何灰色文本时,url 将被加载到同一个 WKWebView 中,当然你可以个性化它以在你做的内部浏览器或其他东西中打开,这取决于你。

然后点击Apple即可立即看到结果:

如果您改为点击 Apple 开发者,您可以看到警报在起作用,因为 http 协议在 iOS 9 中的 HTTPTransportSecurityLayer 中给出错误:

如果您需要,我已准备好将项目上传到 Github。希望对您有所帮助。

【讨论】:

感谢您的详细回答,非常感谢。不幸的是,它并没有解决我的问题,因为我已经正确配置了 WKWebView。 你能在 GitHub 上分享你的项目吗? return true 的答案成功了,所以我不需要进一步的帮助。不过还是谢谢!【参考方案2】:

解决办法是去掉contentInset的使用。不幸的是,WKWebView 不是为处理它的使用而设计的(当contentInset 为负数时),因此我们必须使用一种解决方法,只需在 htmlString 中添加一个空的div,就像这样:

<div style='width:100%;height:100px'></div>

如果要更改底部插图而不重新加载整个页面,可以首先在底部插入一个巨大的div,然后通过添加一个正数contentInset 来补偿它。这正是这个扩展的作用:

extension WKWebView 

   /// The maximum possible height of the webView bottom content inset
   @nonobjc static let maxBottomHeight: CGFloat = 20000

   /// Provides an easy way to set the real bottom inset of the webView. Due to a bug in WKWebView framework, we first insert an emtpy div with the size WKWebView.maxContentSize on the bottom of the webView and compensate it by setting a positive contentInset (should be positive, otherwise the bug will be there again).
   func set(bottomInset inset: CGFloat) 

       self.scrollView.contentInset.bottom = inset - WKWebView.maxBottomHeight
   

不要忘记在 html 字符串的末尾添加div

let htmlFooter = "<div style='width:100%;height:\(String(describing: WKWebView.maxBottomHeight))px'></div></body></html>"

【讨论】:

从 Xcode 10 和 iOS 12 的第一个测试版开始,contentInsets 中的链接不可点击的问题似乎终于得到了解决。【参考方案3】:

当您将内容加载到 WKWebView 时,您可能会为网页设置错误的 baseURL,这会导致链接无效,为了使其正常工作,您应该将 baseURL 设置为正确的 http 或 https URL内容,对于那些工作链接只是因为他们的 href 中有完整的 url。

这里是加载到WKWebView中的html文本来说明效果:

webView.loadHTMLString(content, baseURL: NSURL(string: ""));

内容:

<html lang="en"><head><meta name="viewport" content="width=device-width, initial-scale=1"></head>
    <body>
        <h1> click testing </h1>
        <ul>
            <li><a href="http://www.w3schools.com">Visit W3Schools</a></li>
            <li><a href="/about">Un-Clickable without baseURL</a></li>
            <li><a href="about://about">Clickable without baseURL</a></li>
        </ul>
    </body>
</html>

【讨论】:

不幸的是,它并没有解决我的问题,因为我将一个 html 字符串加载到 webView,而不是网站。 @returnfalse,当然我说的是你的html字符串,那是纯html文本,你介意分享html吗? 感谢您的回答,但这里的问题是,我无法随机打开链接,因此有时特定链接有效,有时无效。如果 baseURL 有问题,它总是不可点击的。 @returnfalse 最好发布一个您遇到问题的项目,如果您长按无效链接会发生什么? return true 的答案成功了,所以我不需要进一步的帮助。不过还是谢谢!

以上是关于WKWebView 中的链接随机不可点击的主要内容,如果未能解决你的问题,请参考以下文章

WKWeb 视图。未调用 didStartProvisionalNavigation

iOS 13 beta 中 WKWebView 的内在内容大小问题

iOS wkWebView点击链接无反应

UIWebView 和 WKWebView 导航

UIWebView 迁移后,WKWebView 中显示的 PDF 中的链接不起作用

关于h5页面,弹框点击确认按钮后会弹出Safari浏览器 问题