27

I am working on the following code and trying to show an activity indicator in the view whilst the page is loading..

I tried to implement the WKNavigationDelegate methods but I am failing as nothing shows.

Any suggestions on how to fix this?

I am not setting the SupportWebView view delegate anywhere but I wouldn't know how to do it in swift..

import UIKit
import WebKit

class SupportWebView: UIViewController, WKNavigationDelegate {
    @IBOutlet var containerView : UIView? = nil

    var webView: WKWebView?

    override func loadView() {
        super.loadView()
        self.webView = WKWebView()
        self.view = self.webView
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        var dataManager = DataManager.sharedDataManager()
        var url = dataManager.myValidURL
        var req = NSURLRequest(URL:url!)
        self.webView!.loadRequest(req)
    }

    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
    }
}
mm24
  • 9,280
  • 12
  • 75
  • 170
  • This code should cause the activity indicator in the status bar to spin. There will be nothing else? Or is it not showing in the status bar either? – Rory McKinnel Mar 31 '15 at 15:50
  • there is no activity indicator showing in the status bar.. would be cool to do something similar to safari, which shows a progress bar... – mm24 Mar 31 '15 at 15:52
  • 3
    You seem to be missing `self.webView.navigationDelegate=self;`? – Rory McKinnel Mar 31 '15 at 15:57
  • 2
    I use this HUD to show progress: https://github.com/jdg/MBProgressHUD. This will put up a nice big activity indicator or progress bar in the middle of the screen. If you want progress you could use a timer to keep updating it and use the `self.webView.estimatedProgress` from the timer to update the HUD progress. – Rory McKinnel Mar 31 '15 at 16:01
  • I added the line @Rory suggested and it works. The activity indicator spins in the upper left corner of the status bar. (iOS 8.3) – MB_iOSDeveloper May 19 '15 at 08:34

3 Answers3

12

As commented, you forgot to set the webView delegate:

override func loadView() {
    super.loadView()
    self.webView = WKWebView()
    self.webView.navigationDelegate = self
    self.view = self.webView
}
Diogo T
  • 2,591
  • 1
  • 29
  • 39
10

You should use the delegate methods for all other purposes, but key path monitoring works fine for this one purpose.

Here is a Swift 4 implementation that works fine.

// Somewhere in your view controller
private var loadingObservation: NSKeyValueObservation?

private lazy var loadingIndicator: UIActivityIndicatorView = {
    let spinner = UIActivityIndicatorView()
    spinner.translatesAutoresizingMaskIntoConstraints = false
    spinner.color = .black
    return spinner
}()

override func viewDidLoad() {
    super.viewDidLoad()

    // Setup...

    loadingObservation = webView.observe(\.isLoading, options: [.new, .old]) { [weak self] (_, change) in
        guard let strongSelf = self else { return }

        // this is fine
        let new = change.newValue!
        let old = change.oldValue!

        if new && !old {
            strongSelf.view.addSubview(strongSelf.loadingIndicator)
            strongSelf.loadingIndicator.startAnimating()
            NSLayoutConstraint.activate([strongSelf.loadingIndicator.centerXAnchor.constraint(equalTo: strongSelf.view.centerXAnchor),
                                         strongSelf.loadingIndicator.centerYAnchor.constraint(equalTo: strongSelf.view.centerYAnchor)])
            strongSelf.view.bringSubview(toFront: strongSelf.loadingIndicator)
        }
        else if !new && old {
            strongSelf.loadingIndicator.stopAnimating()
            strongSelf.loadingIndicator.removeFromSuperview()
        }
    }
}
Oscar Apeland
  • 6,422
  • 7
  • 44
  • 92
5

Please, below code which is working fine[Swift 4.2].

@IBOutlet weak var wv: WKWebView!
@IBOutlet weak var activityIndicator: UIActivityIndicatorView!

override func viewDidLoad() {
    super.viewDidLoad()
     loadYoutube(videoID: "KqNS7uAvOxk")     
}

Now load Youtube Video

 func loadYoutube(videoID:String) {
    guard let youtubeURL = URL(string: "https://www.youtube.com/embed/\(videoID)")
        else { return }
    wv.load( URLRequest(url: youtubeURL) )
    wv.navigationDelegate = self
}

Implement below this function:

 func showActivityIndicator(show: Bool) {
    if show {
        activityIndicator.startAnimating()
    } else {
        activityIndicator.stopAnimating()
    }
}

Implement below these three delegate method:

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

Let me know if it is not working.