Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Links in WKWebView randomly not clickable

In my iOS app written in Swift 2.1, I use a WKWebView to load a HTML string which is loaded from a wordpress blog using a JSON parser.

I implemented the delegate method func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) { and set the navigation delegate of the WKWebView to self in order to handle link presses.

Now, when I open the ViewController which contains the WKWebView, this delegate method gets called once, which is the behaviour you would expect on load of the webView - so the delegate seems to be set properly.

My problem now is that most time the links which the webView contains are not clickable. You would usually expect that a gray background appears, when you a press a link as you can see in the image below. But most time, when I press a link, the gray background doesn't appear, so when I touch up, the delegate method doesn't get called. This problem certainly doesn't have to do something with a misconfiguration of the WKNavigationDelegate, since sometimes the link selection works properly (about 10 %).

appearance of links when you select them

Do you have any idea why links are randomly sometimes not clickable, and sometimes clickable (10 % of the cases)?


like image 886
fredpi Avatar asked Jan 09 '16 12:01

fredpi


1 Answers

I going to suppose that what you want is have some description or text in some place and allow inside some part of the text make clickable/tapped and it's for this that you want to use WKWebView.

I solved this problem using WKWebView too in some app I made a long time ago, of course there are several solutions, it's just one of them, nothing else.

As some people said to you you can use the loadHTMLString function to load the HTML string from your server in JSON or anyway you want, but it's very important that the HTML is good formatted without errors.

A very important point about the loadHTMLString function regarding your comment ...You would usually expect that a a gray background appears when you a press a link as you can see in the image below, it not happen if the HTML don't have some kind of CSS style, because if not it have the default style of any of the <a><\a>.

So let's see the following code:

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

In the above code I set the variable description with some text with clickable elements inside it and added the two delegate methods didStartProvisionalNavigation and didFinishNavigation to show an networkActivityIndicatorVisible in the status bars to show the some progress about the loading of the page when the clickable text it's tapped. It's good to notice that in the htmlString variable I set some styles to show the <a> with some color and font, it's up to you.

I added too the didFailProvisionalNavigation function to show an alert in some case the url is not valid of something like the new HTTPTransportSecurityLayer added is iOS 9 to only allow https, in some cases you can use it to validate the url and know the reason of the error.

The result is the following text in a normal UIViewController:

enter image description here

And when you tap any gray text the url would be loaded inside the same WKWebView, of course you can personalize this to open in a inside browser you do or something else, it's up to you.

And then you can see the result right away if you tap Apple:

enter image description here

If instead you tap Developer Apple you can see the alert in action because the http protocol give an error in the HTTPTransportSecurityLayer in iOS 9:

enter image description here

I have the project ready to upload to Github if you need it. I hope this help you.

like image 144
Victor Sigler Avatar answered Sep 20 '22 16:09

Victor Sigler