WKWebView中的链接随机无法点击

时间:2016-01-09 12:12:50

标签: ios swift wkwebview

在我用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%)。

appearance of links when you select them

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

3 个答案:

答案 0 :(得分: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>"

答案 1 :(得分:1)

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

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

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>

答案 2 :(得分: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 in状态栏显示在点击可点击文本时加载页面的一些进度。值得注意的是,在htmlString变量中,我设置了一些样式以显示<a>一些颜色和字体,这取决于您。

我也添加了didFailProvisionalNavigation功能来显示警告,在某些情况下,网址无效,例如新添加的HTTPTransportSecurityLayer iOS 9只允许 https 在某些情况下,您可以使用它来验证网址并了解错误原因。

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

enter image description here

当你点击任何灰色文字时,网址会被加载到同一个WKWebView中,当然你可以个性化这个以在你做的内部浏览器或其他内容中打开,它& #39;取决于你。

如果您点按 Apple

,您就可以立即看到结果

enter image description here

如果您点击 Developer Apple ,您可以看到警报正在运行,因为 http 协议在iOS 9中的HTTPTransportSecurityLayer中出错:

enter image description here

如果您需要,我已准备好将项目上传到Github。我希望这能帮到你。