Inconsistent Behavior in WKNavigationDelegate - ios

I am working on an app that mainly consist of a WKWebView.
I monitor it's navigation status using the WKNavigationDelegate protocol.
I create my viewController as a WKNavigationDelegate
class ViewController: UIViewController, WKUIDelegate, WKNavigationDelegate, UIGestureRecognizerDelegate {
...
override func viewDidLoad() {
...
webView.navigationDelegate = self
...
I load the request on the webview like so:
let gotoUrl = ... as? String
if let url = URL(string: gotoUrl) {
let request = URLRequest(url: url)
webView.load(request)
}
And then the delegate methods:
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print("Successfully loaded")
}
func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
print("Did commit navigation")
}
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
print("Start Provisional navigation")
}
func webViewWebContentProcessDidTerminate(_ webView:WKWebView) {
print("request failed")
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
print("request failed")
}
func webView(_ webView: WKWebView, didFailProvisionalNavigation: WKNavigation!, withError: Error) {
print("request failed")
}
This works fine for my webapps initial url: https://example.com/app/
Then the delegate methods are called.
When the app is opened from a notification I want to direct the webview to a specific part of the webapp.
However when i load an url that load a specific part of the webapp:
https://example.com/app/#/secure/content/alarm-base/alarm-list//alarm-detail/1381122
The delegate methods are not called, although the webview loads the url successfully.
The delegate methods are also called if I load the specific url directly on startup.
The web appication is written in AngularJS.
I would like for the delegate handlers to trigger for every request I load from the code.
Any idea on how to achieve this?

I am not sure what is going on, but it is possible to force it to use the delegate by adding the following code when doing the request:
webView.load(request)
webView.stopLoading()
webView.reload()
It is clunky, but it solves the problem for me.

Related

switch view if the Webview can't loading the URL?

I have 2 views on my screen first is the Webview and the second is a static view "errorView" with the error message "set to hidden". I am trying to load the errorView if we have an error loading website to Webview.
#objc private func loadURL() {
guard let url = URL(string: "https://www.hackingwi") else {
self.errroLoadingWebView.isHidden = false
return
}
webView?.load(URLRequest(url: url))
webView?.allowsBackForwardNavigationGestures = true
}
You can use WKNavigationDelegate.
set delegate
webView.uiDelegate = self
webView.navigationDelegate = self
class StaticWebPageVC: WKNavigationDelegate, WKUIDelegate {
func webView(_: WKWebView, didFinish _: WKNavigation!) {
// Web view loaded
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
// Show error view
}
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
// Show error view
}
}

URL loading issue in WKWebView

I'm getting a URL from API, I'm passing that URL to my webview and trying to load that, but it isn't loading. I don't know why but it isn't working. Even it's not showing any error or crashes. It's so weird but I don't know what I'm missing in that all the code is written fine. This is my code:
self.loadWeb(webURL: newsUrl!)
func loadWeb(webURL: String) {
let url = URL(string: webURL)
MBProgressHUD.hide(for: self.view, animated: true)
webView.navigationDelegate = self
webView.uiDelegate = self
webView.load(URLRequest(url: url!))
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
webView.frame.size.height = 1
webView.scrollView.isScrollEnabled = false
webView.frame.size = webView.scrollView.contentSize
self.bgViewHeight.constant = webView.frame.size.height
}
private func webView(webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: NSError) {
print(error.localizedDescription)
}
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
print("Start to load")
}
func webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) {
print("finish to load")
}
How i can load this?

Show Image While Loading Webview

I am trying to show an image (logo) while the WKWebView is loading.
So, looking at other posts, I would put an image on the screen in ViewDidLoad() and hide the image in the didFinish method. But, for some reason, the didFinish method is not working. It does not print that it finished (although the webview does show up on the screen). For this, I also already looked at other posts. But, these mainly suggest to set the delegate of the WKWebView (which I did). Here is my code:
import UIKit
import Foundation
import WebKit
class ViewController: UIViewController, WKUIDelegate {
var webView: WKWebView!
override func loadView() {
let webConfiguration = WKWebViewConfiguration()
webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.uiDelegate = self
view = webView
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let myURL = URL(string:"https://www.mijnmedicijn.nl/")
let myRequest = URLRequest(url: myURL!)
webView.load(myRequest)
}
func webView(_ webView: WKWebView,
didFinish navigation: WKNavigation!){
print("Webview did finish load")
}
func webView(_ webView: WKWebView,
didStart navigation: WKNavigation!){
print("Webview did start laoding")
}
}
What am I doing wrong? Why doesn't the didFinish work? How would I make it work and show an image while loading?
You need to add the delegate of the navigation
webView.navigationDelegate = self
class ViewController: UIViewController , WKUIDelegate , WKNavigationDelegate {
First of all, optional func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) is a method declared in WKNavigationDelegate hence your class must conform to protocol WKNavigationDelegate and your code must look like webView.navigationDelegate = self
Secondly, for your another question in comments "Why does it print the statement seconds after the webview is already loaded on my phone?"
The optional func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) is called when webview mainframe navigation gets completed i.e. WKWebView fully completes loading the entire page.
An ideal implementation for showing/hiding loading image would be,
Conform to WKNavigationDelegate.
Implement optional func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) and write code to show the loading image in this function. As this function gets called as soon as WKWebView starts mainframe navigation.
Implement optional func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) and write code to hide the loading image in this function. As this function gets called as soon as contents start arriving in WKWebView.
Also implement optional func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) and write code to hide the loading image in this function. This function should be implemented just-in-case URL loading fails.

how to hide html elements in wkwebview in IOS?

i want to hide certain html elements in wkwebview using swift 4, xcode 9. i know how to do it in android and have added the code below. i just need an equivalent code for ios in swift 4 for wkwebView.
myWebView.setWebViewClient(new WebViewClient()
{
#Override
public void onPageFinished(WebView view, String url)
{
myWebView.loadUrl("javascript:(function() { " +
"document.getElementById('divHeader')
[0].style.display='none'; " +
"})()");
}
});
myWebView.loadUrl(URL);
Use WKWebView
import WebKit
class FirstViewController: UIViewController, WKNavigationDelegate {
#IBOutlet weak var webVw: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
webVw.navigationDelegate = self
loadmyPage(htmlstr: "https://www.mywebsite.com")
}
func loadmyPage(htmlstr:String){
let url = URL (string: htmlstr)
let request = URLRequest(url: url!)
webVw.load(request)
}
//MARK:- WKNavigationDelegate
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
print(error.localizedDescription)
}
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
print("Start to load")
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print("finish to load")
let elementID = "right_sidebar"
let removeElementIdScript = "var element = document.getElementById('\(elementID)'); element.parentElement.removeChild(element);"
webView.evaluateJavaScript(removeElementIdScript) { (response, error) in
debugPrint("Am here")
}
}

Activity Indicator won't stop spinning after WKWebView load finish

I am very new to Swift and iOS development so thank you so much in advance for helping me!
I have tried every example online and every page on this site and I cannot get my Activity Indicator to stop being displayed once the page completes loading in my WKWebview.
Any assistance would be so appreciated! Thank you!
import UIKit
import WebKit
class FirstViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {
#IBOutlet var webView: WKWebView!
#IBOutlet var activityIndicator: UIActivityIndicatorView!
override func viewDidLoad() {
super.viewDidLoad()
webView.uiDelegate = self
activityIndicator.startAnimating()
activityIndicator.isHidden = true
activityIndicator.hidesWhenStopped = true
let url = Bundle.main.url(forResource: "Web/bulk_material_table", withExtension: "html")!
webView.loadFileURL(url, allowingReadAccessTo: url)
let request = URLRequest(url: url)
self.webView.load(request)
}
func showActivityIndicator(show: Bool) {
if show {
activityIndicator.startAnimating()
} else {
activityIndicator.stopAnimating()
}
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
showActivityIndicator(show: false)
}
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
showActivityIndicator(show: true)
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
showActivityIndicator(show: false)
}
}
Just replace
webView.uiDelegate = self
with
webView.navigationDelegate = self
And it will work because
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
showActivityIndicator(show: false)
}
is WKNavigationDelegate's delegate method.

Resources