How to check if WkWebView finish loading in Objective-C?
Asked Answered
F

4

67

I want to load HTML pages using WkWebView and I want to show the page just after it's finished loading. As long as it's loading I would like to show an activity indicator on an empty View. I create two view a loadingView and a wkWebView. While the page is loading I add to VC as subview the loadingView and after I want to remove loadingView and add wkWebView. Here is my code:

    [self addSubview:_loadingView];
    _wkWebView = [[WKWebView alloc] initWithFrame:self.frame];
    _wkWebView.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, self.frame.size.height);

    //Send a request to wkUrlconnection
    NSURL *wkUrl = [NSURL URLWithString:self.wkUrlString];
    NSURLRequest *wkRequest = [NSURLRequest requestWithURL:wkUrl];

    //Here I want to check if it's loaded and then remove loadingView and add wkWebView
    [_wkWebView loadRequest:wkRequest];
    [self.loadingView removeFromSuperview];
    [self addSubview:_wkWebView];

Can someone show me how to check while it's loading and if finish refresh the VC? Thank you for your answers.

Fumatorium answered 30/3, 2016 at 15:26 Comment(2)
Have you looked at the delegate-pattern and how it is used with the navigationDelegate property on an WKWebView?Shiite
Thanks Mats. I need this.Fumatorium
R
85

I think the WKNavigationDelegate's webView:didFinishNavigation: delegate callback is what you're looking for.

Configure and present your activity indicator when you start to load and then stop and remove it from view when the callback is called.

Riella answered 30/3, 2016 at 15:42 Comment(5)
Thank you. This was the good solution, but let me correct you. WkWebView doesn't have WKWebViewDelegate. Instead of that, it has WKNavigationDelegate.Fumatorium
An extended question, can WebView get response like URLSession when finish loading?Brookner
That method may be called multiple times for multiple frames so it does not workIndianapolis
Any solution to know when it's completely loaded and method not called againTrudge
webView:didFinishNavigation: Call back will not come most of the time its not working for meUnderdrawers
C
17

For anyone who is experiencing the issue of a webpage containing multiple frames and therefore doing multiple loads which interrups your load animation, I have implemented the following and it works for me in all the situations I have come across so far:

Swift:

var loadCount: Int = 0

override func viewDidLoad() {
    super.viewDidLoad()

    startLoading()
    webview.navigationDelegate = self
    let request = URLRequest(url: url)
    webview.load(request)
}

func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
    loadCount += 1
}

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {

    loadCount -= 1

    DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in
        if self?.loadCount == 0 {
            self?.stopLoading()
        }
    }

}

The basic idea is to start your load animation before you request the url, then count each request being made and only stop the load animation when your request count == 0. This is done after a slight delay as I find that some frames queue up requests synchronously so the next load will begin before the 0.1 second delay has completed.

( ͡° ͜ʖ ͡°)

Crowning answered 12/2, 2019 at 11:38 Comment(2)
This may not work serval times, there is no guarantee for every didStartProvisionalNavigation you will get didFinish navigation, so the count never comes to 0 that cases.Falconet
How about it in Objective C as that's what the question demandsSiobhansion
A
13

for swift 4.2:

func webView(_ webView: WKWebView,
                 didFinish navigation: WKNavigation!){
        print("loaded")
}

be sure to set delegate for webView in didLoad (or similar)

webView.navigationDelegate = self
Alible answered 29/12, 2018 at 7:13 Comment(6)
But this is not for Objective C as RequestedSiobhansion
I do know. my two cents for Swift, objC is dead :)Alible
Objective C is not dead. It just smells funny.Jackofalltrades
I did love it very much, but when I go back I miss all the new swift conciseness and features. :(Alible
Objective C will never die. There are those of us supporting legacy code that will live forever, just like those poor bastards who had to dig through COBOL code in 1999.Appassionato
and Cobol guys do earn much more than us :)Alible
R
2
class WebViewVC: UIViewController {
    
    // MARK: IBOutlets
    @IBOutlet weak var webView: WKWebView!
    @IBOutlet weak var activityIndicator: UIActivityIndicatorView!
    
    // MARK: Life cycle
    override func viewDidLoad() {
        super.viewDidLoad()
        
        webView.navigationDelegate = self
        loadWebsite()
    }
}

// MARK: WKWebView
extension WebViewVC: WKNavigationDelegate {
    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        activityIndicator.startAnimating()
    }
    
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        activityIndicator.stopAnimating()
    }
}

// MARK: Private methods
extension WebViewVC {
    private func loadWebsite() {
        guard let url = URL(string: "google.com") else { return }
        
        let urlRequest = URLRequest(url: url)
        webView.load(urlRequest)
    }
}
Ratel answered 14/1, 2021 at 15:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.