Skip to content

Instantly share code, notes, and snippets.

@fxm90
Last active October 24, 2024 17:52
Show Gist options
  • Save fxm90/50d6c73d07c4d9755981b9bb4c5ab931 to your computer and use it in GitHub Desktop.
Save fxm90/50d6c73d07c4d9755981b9bb4c5ab931 to your computer and use it in GitHub Desktop.
Show progress of WKWebView in UIProgressBar that is attached to an UINavigationBar
//
// WebViewExampleViewController.swift
//
// Created by Felix Mau on 06.01.18.
// Copyright © 2018 Felix Mau. All rights reserved.
//
import UIKit
import WebKit
final class WebViewExampleViewController: UIViewController {
// MARK: - Outlets
/// The web view from the interface builder.
@IBOutlet private var webView: WKWebView!
// MARK: - Private properties
/// Progress view reflecting the current loading progress of the web view.
private let progressView = UIProgressView(progressViewStyle: .default)
/// The observation object for the progress of the web view (we only receive notifications until it is deallocated).
private var estimatedProgressObserver: NSKeyValueObservation?
// MARK: - Public methods
override func viewDidLoad() {
super.viewDidLoad()
setupProgressView()
setupEstimatedProgressObserver()
if let initialUrl = URL(string: "https://felix.hamburg") {
setupWebview(url: initialUrl)
}
}
// MARK: - Private methods
private func setupProgressView() {
guard let navigationBar = navigationController?.navigationBar else {
print("⚠️ – Expected to have a valid navigation controller at this point.")
return
}
progressView.isHidden = true
progressView.translatesAutoresizingMaskIntoConstraints = false
navigationBar.addSubview(progressView)
NSLayoutConstraint.activate([
progressView.leadingAnchor.constraint(equalTo: navigationBar.leadingAnchor),
progressView.trailingAnchor.constraint(equalTo: navigationBar.trailingAnchor),
progressView.bottomAnchor.constraint(equalTo: navigationBar.bottomAnchor),
progressView.heightAnchor.constraint(equalToConstant: 2.0)
])
}
private func setupEstimatedProgressObserver() {
estimatedProgressObserver = webView.observe(\.estimatedProgress, options: [.new]) { [weak self] webView, _ in
self?.progressView.progress = Float(webView.estimatedProgress)
}
}
private func setupWebview(url: URL) {
webView.navigationDelegate = self
let request = URLRequest(url: url)
webView.load(request)
}
}
// MARK: - WKNavigationDelegate
/// By implementing the `WKNavigationDelegate` we can update the visibility of the `progressView` according to the `WKNavigation` loading progress.
///
/// - SeeAlso: [fxm90/UIView+AnimateIsHidden.swift](https://gist.github.com/fxm90/723b5def31b46035cd92a641e3b184f6)
extension WebViewExampleViewController: WKNavigationDelegate {
func webView(_: WKWebView, didStartProvisionalNavigation _: WKNavigation!) {
if progressView.isHidden {
// Make sure our animation is visible.
progressView.isHidden = false
}
UIView.animate(withDuration: 0.33,
animations: {
self.progressView.alpha = 1.0
})
}
func webView(_: WKWebView, didFinish _: WKNavigation!) {
UIView.animate(withDuration: 0.33,
animations: {
self.progressView.alpha = 0.0
},
completion: { isFinished in
// Update `isHidden` flag accordingly:
// - set to `true` in case animation was completly finished.
// - set to `false` in case animation was interrupted, e.g. due to starting of another animation.
self.progressView.isHidden = isFinished
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment