Created
January 10, 2017 06:46
-
-
Save fahied/698e6f3a09d898b0020d1d4775ffef93 to your computer and use it in GitHub Desktop.
WKWebView controller example with progress bar
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// MyWKWebVC.Swift | |
// Example | |
// | |
// Created by Fahied on 04/01/2017. | |
// | |
import Foundation | |
import UIKit | |
import WebKit | |
var myContext = 0 | |
class MyWKWebVC: UIViewController { | |
var webView: WKWebView! | |
var package: NSDictionary! | |
var progressView: UIProgressView! | |
//init | |
override func loadView() { | |
//add webview | |
webView = WKWebView() | |
webView.navigationDelegate = self | |
view = webView | |
//add progresbar to navigation bar | |
progressView = UIProgressView(progressViewStyle: .default) | |
progressView.autoresizingMask = [.flexibleWidth, .flexibleTopMargin] | |
progressView.tintColor = #colorLiteral(red: 0.6576176882, green: 0.7789518833, blue: 0.2271372974, alpha: 1) | |
navigationController?.navigationBar.addSubview(progressView) | |
let navigationBarBounds = self.navigationController?.navigationBar.bounds | |
progressView.frame = CGRect(x: 0, y: navigationBarBounds!.size.height - 2, width: navigationBarBounds!.size.width, height: 2) | |
} | |
//deinit | |
deinit { | |
//remove all observers | |
webView.removeObserver(self, forKeyPath: "title") | |
webView.removeObserver(self, forKeyPath: "estimatedProgress") | |
//remove progress bar from navigation bar | |
progressView.removeFromSuperview() | |
} | |
//viewcontroller | |
override func viewDidLoad() { | |
webView.load(myRequest()) | |
webView.allowsBackForwardNavigationGestures = true | |
// // add observer for key path | |
webView.addObserver(self, forKeyPath: "title", options: .new, context: &myContext) | |
webView.addObserver(self, forKeyPath: "estimatedProgress", options: .new, context: &myContext) | |
} | |
//actions | |
func doneTapped() { | |
//Routing is your class handle view routing in your app | |
Routing.showAnotherVC(fromVC: self) | |
} | |
//observer | |
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { | |
guard let change = change else { return } | |
if context != &myContext { | |
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) | |
return | |
} | |
if keyPath == "title" { | |
if let title = change[NSKeyValueChangeKey.newKey] as? String { | |
self.navigationItem.title = title | |
} | |
return | |
} | |
if keyPath == "estimatedProgress" { | |
if let progress = (change[NSKeyValueChangeKey.newKey] as AnyObject).floatValue { | |
progressView.progress = progress; | |
} | |
return | |
} | |
} | |
//compute your url request | |
func myRequest() -> URLRequest { | |
return URLRequest(url: (URL(string: "https://google.com") | |
} | |
func addDoneButton() { | |
let done = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneTapped)) | |
navigationItem.rightBarButtonItems = [done] | |
} | |
func hideBackButton() { | |
navigationItem.setHidesBackButton(true, animated: false) | |
} | |
} | |
extension PaymentVC: WKNavigationDelegate { | |
//WKNavigationDelegate | |
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { | |
if let url = navigationAction.request.url { | |
if url.absoluteString.contains("/something") { | |
// if url contains something; take user to native view controller | |
Routing.showAnotherVC(fromVC: self) | |
decisionHandler(.cancel) | |
} else if url.absoluteString.contains("done") { | |
//in case you want to stop user going back | |
hideBackButton() | |
addDoneButton() | |
decisionHandler(.allow) | |
} else if url.absoluteString.contains("AuthError") { | |
//in case of erros, show native allerts | |
} | |
else{ | |
decisionHandler(.allow) | |
} | |
} | |
} | |
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { | |
progressView.isHidden = true | |
} | |
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) { | |
progressView.isHidden = false | |
} | |
} |
Great! The use of observer solved my problem i.e. webview content is loaded first followed by title for navigation item.
var observers: [NSKeyValueObservation] = []
let obs = webView.observe(\.title, options: .new) {[weak self] webView, _ in
self?.navBarTitle?.text = webView.title
}
observers.append(obs)
let progressObs = webView.observe(\.estimatedProgress, options: .new) {[weak self] webView, _ in
self?.progressView.progress = Float(webView.estimatedProgress)
}
observers.append(progressObs)
let isLoadingObs = webView.observe(\.isLoading, options: .new) {[weak self] webView, _ in
self?.progressView.isHidden = webView.isLoading
}
observers.append(isLoadingObs)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Can you please help solving "Block Based KVO Violation: Prefer the new block based KVO API with keypaths when using Swift 3.2 or later. (block_based_kvo)" warning while using wkwebview progress bar