如何在Objective-C中检查WkWebView是否加载完成?

67

我想使用WkWebView加载HTML页面,并在页面完成加载后立即显示该页面。只要它在加载,我想在空视图上显示活动指示器。 我创建了两个视图,一个是loadingView,另一个是wkWebView。当页面正在加载时,我将loadingView添加到VC作为子视图,之后我想删除loadingView并添加wkWebView。以下是我的代码:

    [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];

有人可以向我展示如何在加载时检查,如果完成则刷新视图控制器吗?感谢您的回答。


你是否了解过委托模式,以及它如何与WKWebView上的navigationDelegate属性一起使用? - Mats
谢谢Mats。我需要这个。 - faklyasgy
4个回答

85

我认为WKNavigationDelegatewebView:didFinishNavigation:代理回调是您要寻找的内容。

在开始加载时配置和显示您的活动指示器,然后在回调被调用时停止并将其从视图中删除。


5
谢谢。这个方案是正确的,但请允许我纠正您一下。WkWebView 并没有 WKWebViewDelegate。相反,它有 WKNavigationDelegate。 - faklyasgy
一个扩展的问题,当WebView完成加载时,它能否像URLSession一样获取响应? - allenlinli
6
该方法可能会被多次调用以处理多个帧,因此它无法正常工作。 - apinho
3
如何知道一个页面完全加载完成且方法不被再次调用的解决方案。 - Chandni
4
webView:didFinishNavigation: 回调通常不会触发,对我来说它经常无法正常工作。 - Piyush

17

对于那些遇到包含多个框架的网页并因此进行多次加载而打断您的加载动画的人,我已经实现了以下内容,并且在迄今为止遇到的所有情况中都有效:

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

}

基本思想是在请求URL之前启动您的加载动画,然后计算每个请求并仅在您的请求计数==0时停止加载动画。这是在稍微延迟后完成的,因为我发现一些帧会同步排队请求,因此下一个加载将在0.1秒延迟完成之前开始。

( ͡° ͜ʖ ͡°)


这可能不止一次失效,每个didStartProvisionalNavigation都不能保证会得到didFinish navigation,所以计数永远不会降为0。 - me-wright
那么我们用Objective C怎么样?因为这是问题所要求的。 - Ahmed El-Bermawy

13

对于Swift 4.2:

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

确保在didLoad(或类似方法)中为webView设置代理

webView.navigationDelegate = self

1
但是这不是所要求的 Objective C。 - Ahmed El-Bermawy
1
我知道。对于Swift,objC已经死了 :) - ingconti
Objective C并不已死。它只是有点奇怪的气味。 - dar512
我非常喜欢它,但是当我回去时,我会想念所有新的Swift简洁和功能。 :( - ingconti
1
Objective C永远不会死。我们这些支持遗留代码的人将会永生,就像那些可怜的家伙在1999年不得不挖掘COBOL代码一样。 - spartygw
COBOL的程序员比我们挣得多 :) - ingconti

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接