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 %).
Do you have any idea why links are randomly sometimes not clickable, and sometimes clickable (10 % of the cases)?
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
:
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:
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:
I have the project ready to upload to Github if you need it. I hope this help you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With