My question:
How do I check if a page in WKWebView has fully loaded in Xcode using Swift 3?
This is my problem:
Webpage 1:
From this page I load Webpage 2
Webpage 2:
I need to get html data from Webpage 2, but when I print the HTML data I get HTML data of webpage 1, which I don't want. But when I print HTML data 2 seconds later it gives me the right HTML data.
I need to know whether or not a page in WKWebView did finish loading. I can see in the WebView it is loaded and also the progressbar is fully loaded, but when I print html data of the page I get html data of previous page, which is not what I want. Only if I wait a second it gives the right data, probably cause Webpage 2 is loaded.
So how do I let Xcode to print html when the next page is totally loaded?
I have tried several methods:
detect WKWebView finish loading
Call JavaScript function from native code in WKWebView
Maybe I can use:
if webView.isloading { get }
but I don't know how to implement this method and if it should work.
I have tried several methods from Stack but these are not working for me or outdated.
Do you guys know a solution for this problem in Swift 3?
Thanks!
Answer (Big thanks to #paulvs )
To check if your WKWebView has loaded easily implement the following method:
import WebKit
import UIKit
class ViewController: UIViewController, WKNavigationDelegate {
let webView = WKWebView()
func webView(_ webView: WKWebView,
didFinish navigation: WKNavigation!) {
print("loaded")
}
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: "https://www.yourwebsite.com/") !
let request = URLRequest(url: url)
webView.navigationDelegate = self
webView.load(request)
// Do any additional setup after loading the view, typically from a nib.
}
}
Add WKNavigationDelegate to class
Add:
func webView(_ webView: WKWebView,didFinish navigation: WKNavigation!) { print("loaded") }
Result: It will print "loaded" in the console everytime the WKWebView has finished loading the page. This was excactly what I was looking for, so again a big thanks to Paulvs!
Set delegate > WKNavigationDelegate
Objective-C
// Start loading WKWebView
-(void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {
NSLog(#"Start loading");
}
//Finished loading WKWebView
-(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
NSLog(#"End loading");
}
Swift 4.2
func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
print("Start loading")
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print("End loading")
}
Related
I am having difficulty getting a WKWebview to call its delegate methods, namely the did finish one.
I am attempting something similar to this post generating a pdf report using html loaded into a WKWebView;
WKWebView not calling navigation delegate methods
However trying the suggestion there, that doesn't work for me. I have a WKWebView made in a separate class to the View controller that will be calling its methods.
If I strip things right down and just try to simply load a website in the WebView to see if the delegate functions get called I get nothing.
Here is my test class;
import UIKit
import WebKit
class TestWebview: NSObject {
let webView = WKWebView ()
func loadWebsite () {
print ("LOAD TEST CALLED")
webView.navigationDelegate = self
let link = URL(string: "https://www.apple.com")!
let request = URLRequest(url: link)
webView.load(request)
}
}
extension TestWebview: WKNavigationDelegate {
func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
print ("DID COMMIT")
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print ("FINISHED LOADING")
}
}
And here is how I am calling it in a separate view controller;
override func viewDidLoad() {
super.viewDidLoad()
let test = TestWebview ()
test.loadWebsite()
}
Although if I put a WKWebView as an outlet into a view controller using Storyboards then the delegate methods do get called. I am trying to avoid this however as I don't want to see a web view in the view controller and want to keep all the code for that separate in another class.
Am I missing something? Checking various other posts on Stack Overflow about this hasn't given me any solutions other than making sure the navigation delegate is being set, which I am. Any help would be greatly appreciated.
You need to move let test = TestWebview () to class level, otherwise this object is going to be evicted when viewDidLoad completes: the navigationDelegate is defined as weak, so it's not going to prevent it either.
I am trying to view the website https://www.methodenguide.de/basic inside a WKWebView. The website itself loads, but it doesn't behave as it should or as it does in Safari:
The boxes on the homepage don't show images
Links don't load targetet urls (didFinish navigation method says page is loaded instantly, but in fact nothing seems to happen)
Navigation menu is not shown properly (compared to Safari view).
The website works perfectly in Safari on the iPhone, so there seems to be a problem with the WKWebView, but I have no clue where to look ...
Any help is appreciated, as I'm fairly new to iOS / Swift development!
Thanks in advance, everybody :)
#IBOutlet weak var website: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
website.navigationDelegate = self
let request = URLRequest(url: URL(string: "https://www.methodenguide.de/basic")!)
website.load(request)
website.addObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress), options: .new, context: nil)
website.addObserver(self, forKeyPath: #keyPath(WKWebView.title), options: .new, context: nil)
}
func webView(_ website: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!)
{
print("Began loading page")
}
func webView(_ website: WKWebView,
didFinish navigation: WKNavigation!)
{
print("Finished loading page")
}
The answer lies in the info.plist. You need to enable http (not secure) connections as the images are loaded via ajax or the certificate is not secure.
App Transport Security Settings:
Allow Arbitrary Loads in Web Content
Allow Arbitrary Loads
Set both to YES.
I am loading two websites in two different web views and after loading website i am hiding some content of it which is working perfect using WKNavigationDelegate did finish method.
but issue is did finish function is calling about 90 sec after loading website in web view.
Function is working fine but i just want to know why this function is loading too late it should execute function right after loading website.
my code is
web_view.navigationDelegate = self as? WKNavigationDelegate
web_view.isUserInteractionEnabled = true
let request = URLRequest(url: url!)
self.web_view.load(request)
self.view.addSubview(self.web_view)
delegate method
extension urdu_HomeViewController : WKNavigationDelegate{
//enable javascript to remove vavigation from website
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
let removeelementid = "javascript:(function() { " + "document.getElementsByClassName('td-header-menu-wrap-full td-container-wrap')[0].style.display=\"none\"; " + "})()"
webView.evaluateJavaScript(removeelementid) { (res, error) in
if error != nil
{
print("Error")
}
else
{
//print(res!)
}
}
}
WKNavigationDelegate didFinish method is called only after all subresources are loaded. So in your case it might be that some resource takes too much time to load and that delays calling didFinish.
You should rather use WKUserScript to execute your JS right after DOM is ready.
I am making an application that loads a UIWeb View and runs a line of code the moment the webpage is completely loaded.
I am using code like this to load the webpage:
let links = URL (string: "https://example.com")
let loadpage = URLRequest(url: links!)
webPage.loadRequest(load)
How can I run a piece of code the moment the webpage is done? I have tried some examples online but the webpage stops loading while checking if it has loaded?
Thanks!
As stated in the documentation of UIWebView, for apps targeting iOS8 or later you should be using WKWebView instead.
When using a WKWebView, you can make your class conform to WKNavigationDelegate and the delegate method func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) will be called once the webview finishes loading a network request.
If for some reason you are still targeting iOS7 or any previous iOS versions and hence the use of a UIWebView, you can use UIWebViewDelegate's func webViewDidFinishLoad(_ webView: UIWebView) method instead.
Skeleton code for the UIWebView solution:
class WebVC: UIViewController {
#IBOutlet weak var webView: UIWebView!
override func viewDidLoad() {
webView.delegate = self
let url = URL(string: "https://example.com")
let request = URLRequest(url: url)
webView.loadRequest(request)
}
}
extension WebVC: UIWebViewDelegate {
func webViewDidFinishLoad(_ webView: UIWebView) {
print("Finished loading")
}
}
That's what I'm doing:
Loading the page in WKWebView
Pressing the button on the page
As a result I can get either valid URL, either invalid URL. How do I check if I've got the valid one? I need something like URLThatWasLoadedInWKWebView == "myValidURL"?
var webView: WKWebView!
var webUrl="google.com"
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: webUrl)!
let urlRequest = URLRequest(url: url)
webView.load(urlRequest)
view.insertSubview(webView, at: 0)
}
After I clicked on the button, I need to check that the page has loaded the valid "mail.google.com"
If you have your view controller conform to the WKNavigationDelegate then you can use those delegate functions to get the information you're looking for.
Inside this delegate function:
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!)
You could check the webView.url which shows you the url that the web view just loaded. You could use that to check against whatever url you are trying to check against.