WKWebView: Use same delegate code (WKNavigationDelegate) in multiple view controllers - ios

I have an application with 5 navigation tabs, each one with a different View Controller that has a WKWebView inside it. I would like to somehow use the same delegate code to prevent copy and pasting in each one.
How do I reuse the "decidePolicyFor" code in different View Controllers?
class DashboardViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {
var webView: WKWebView!
override func loadView() {
let webConfiguration = WebViewUtils.getWKWebViewConfiguration()
webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.uiDelegate = self
webView.navigationDelegate = self
view = webView
}
override func viewDidLoad() {
super.viewDidLoad()
webView.load(Constants.DASHBOARD)
}
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: #escaping (WKNavigationActionPolicy) -> Void) {
if navigationAction.request.url?.scheme == "tel" {
UIApplication.shared.open(navigationAction.request.url!, options: convertToUIApplicationOpenExternalURLOptionsKeyDictionary([:]), completionHandler: nil)
decisionHandler(.cancel)
}
else {
decisionHandler(.allow)
}
}
}

You can implement this by dependency injection like this:
class NavigationBehavior: NSObject, WKNavigationDelegate {
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: #escaping (WKNavigationActionPolicy) -> Void) {
if let url = navigationAction.request.url, url.scheme == "tel" {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
decisionHandler(.cancel)
} else {
decisionHandler(.allow)
}
}
}
class DashboardViewController: UIViewController, WKUIDelegate {
lazy var webView: WKWebView = {
let webConfiguration = WKWebViewConfiguration()
return WKWebView(frame: .zero, configuration: webConfiguration)
}()
let navigationDelegate: WKNavigationDelegate
init(navigationDelegate: WKNavigationDelegate) {
self.navigationDelegate = navigationDelegate
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func loadView() {
webView.uiDelegate = self
webView.navigationDelegate = navigationDelegate
view = webView
}
override func viewDidLoad() {
super.viewDidLoad()
webView.load(Constants.DASHBOARD)
}
}
let delegate = NavigationBehavior()
let vc1 = DashboardViewController(navigationDelegate: delegate)
let vc2 = ProfileViewController(navigationDelegate: delegate)

You can extract the navigation delegate code in an object like this:
class MyWebViewNavigationDelegate: NSObject, WKNavigationDelegate {
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: #escaping (WKNavigationActionPolicy) -> Void) {
if navigationAction.request.url?.scheme == "tel" {
UIApplication.shared.open(navigationAction.request.url!, options: [:], completionHandler: nil)
decisionHandler(.cancel)
} else {
decisionHandler(.allow)
}
}
}
and then use instances of this object throughout the app:
class DashboardViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {
var webView: WKWebView!
let webViewNavigationDelegate = MyWebViewNavigationDelegate()
override func loadView() {
let webConfiguration = WebViewUtils.getWKWebViewConfiguration()
webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.uiDelegate = self
webView.navigationDelegate = webViewNavigationDelegate
view = webView
}
override func viewDidLoad() {
super.viewDidLoad()
webView.load(Constants.DASHBOARD)
}
}

Related

Getting an ios storyboard webView app to render in safe area

Probably a simple fix but I'm trying to get my simple ios storyboard app to render in the safe area on my iPhone 11.
It's currently taking up the entire view space and not using the safe area. I'm not confident whether I need to make any changes to the code or is it simply a setting in the storyboard view which is not on.
It's my first app. Thanks for your help.
import UIKit
import WebKit
class ViewController: UIViewController, WKUIDelegate {
var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let myURL = URL(string:"https://google.com")
let myRequest = URLRequest(url: myURL!)
webView.load(myRequest)
if #available(iOS 11.0, *) {
webView.scrollView.contentInsetAdjustmentBehavior = .never;
}
webView.navigationDelegate = self
webView.allowsBackForwardNavigationGestures = true
}
override func loadView() {
let webConfiguration = WKWebViewConfiguration()
webConfiguration.dataDetectorTypes = [.all]
webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.uiDelegate = self
view = webView
}
}
extension ViewController: WKNavigationDelegate {
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction,
decisionHandler: #escaping (WKNavigationActionPolicy) -> Void) {
guard
let url = navigationAction.request.url else {
decisionHandler(.cancel)
return
}
let string = url.absoluteString
if (string.contains("mailto:")) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
decisionHandler(.cancel)
return
}
if (string.contains("sms:")) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
decisionHandler(.cancel)
return
}
decisionHandler(.allow)
}
}
class FullScreenWKWebView: WKWebView {
override var safeAreaInsets: UIEdgeInsets {
return UIEdgeInsets(top: 100, left: 0, bottom: 0, right: 0)
}
}
That's happening because you're setting the webView as the controller's view. I think the easiest approach is by setting the webView as a subView of the viewController main view. Start by moving the initialisation code from the loadView method to the viewDidLoad, add the webView as a subView and finally constrainer the webView anchors to the safeArea anchors.
import UIKit
import WebKit
class ViewController: UIViewController, WKUIDelegate {
var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let webConfiguration = WKWebViewConfiguration()
webConfiguration.dataDetectorTypes = [.all]
webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.uiDelegate = self
webView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(webView)
NSLayoutConstraint.activate([
webView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
webView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
webView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
webView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
])
let myURL = URL(string:"https://google.com")
let myRequest = URLRequest(url: myURL!)
webView.load(myRequest)
if #available(iOS 11.0, *) {
webView.scrollView.contentInsetAdjustmentBehavior = .never;
}
webView.navigationDelegate = self
webView.allowsBackForwardNavigationGestures = true
}
}
extension ViewController: WKNavigationDelegate {
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction,
decisionHandler: #escaping (WKNavigationActionPolicy) -> Void) {
guard
let url = navigationAction.request.url else {
decisionHandler(.cancel)
return
}
let string = url.absoluteString
if (string.contains("mailto:")) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
decisionHandler(.cancel)
return
}
if (string.contains("sms:")) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
decisionHandler(.cancel)
return
}
decisionHandler(.allow)
}
}
If the previous option is not valid, you can use your code and change the webView bounds using the viewSafeAreaInsetsDidChange method, making it aware of the safe area insets. Just add the following code:
override func viewSafeAreaInsetsDidChange() {
super.viewSafeAreaInsetsDidChange()
view.bounds = view.safeAreaLayoutGuide.layoutFrame
}

IOS WKWebview Cache Clearing

I have made a very simple WKWebview IOS app that embeds my Wordpress website ...
import UIKit
import WebKit
class ViewController: UIViewController {
private lazy var url = URL(string: "http://www.myblog.com")!
private weak var webView: WKWebView!
init (url: URL, configuration: WKWebViewConfiguration) {
super.init(nibName: nil, bundle: nil)
self.url = url
navigationItem.title = ""
}
required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
override func viewDidLoad() {
super.viewDidLoad()
initWebView()
webView.loadPage(address: url)
}
private func initWebView() {
let webView = WKWebView(frame: .zero, configuration: WKWebViewConfiguration())
view.addSubview(webView)
self.webView = webView
webView.navigationDelegate = self
webView.uiDelegate = self
webView.translatesAutoresizingMaskIntoConstraints = false
webView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
webView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor).isActive = true
webView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
webView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true
}
}
extension ViewController: WKNavigationDelegate {
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
guard let host = webView.url?.host else { return }
navigationItem.title = host
}
}
extension ViewController: WKUIDelegate {
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
guard navigationAction.targetFrame == nil,
let url = navigationAction.request.url else { return nil }
let vc = ViewController(url: url, configuration: configuration)
if let navigationController = navigationController {
navigationController.pushViewController(vc, animated: false)
return vc.webView
}
present(vc, animated: true, completion: nil)
return nil
}
}
extension WKWebView {
func loadPage(address url: URL) { load(URLRequest(url: url)) }
func loadPage(address urlString: String) {
guard let url = URL(string: urlString) else { return }
loadPage(address: url)
}
}
There is a caching plugin on the actual website and I would like for whenever the app loads on a users device - for the app to pull in a fresh copy of the url. Is this possible?
Can anyone advise where to start or how i can adjust my current code to get started?
Thank you!
Push notifications has nothing to do with the WKWebview.
First you need to handle events in the backend/wordpress. From the mobile side, you need the following:
1- Generating a P12 or P8 certificate and put it on the server to trust APN
2- Register for push notifications in AppDelegate class.
3- Handle receiving a push notification in AppDelegate class too.

WKWebView: mailto links in html content not opening mail app

I created a very simple iOS app (Swift 5). It's just a WKWebView that loads my PWA url.
Everything works fine except all Mail me links. When I click them, nothing happens, my mail app doesn't open.
This is the code of my ViewController.swift:
//
// ViewController.swift
// panel
//
// Created by kevin on 25/07/2019.
// Copyright © 2019 umono. All rights reserved.
//
import UIKit
import WebKit
class ViewController: UIViewController, WKUIDelegate {
var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let myURL = URL(string:"https://someUrlToMyApp.appspot.com")
let myRequest = URLRequest(url: myURL!)
webView.load(myRequest)
if #available(iOS 11.0, *) {
webView.scrollView.contentInsetAdjustmentBehavior = .never;
}
}
override func loadView() {
let webConfiguration = WKWebViewConfiguration()
webConfiguration.dataDetectorTypes = [.all]
webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.uiDelegate = self
view = webView
}
}
EDIT:
Thx guy's, here is my working code:
//
// ViewController.swift
// panel
//
// Created by kevin on 25/07/2019.
// Copyright © 2019 umono. All rights reserved.
//
import UIKit
import WebKit
class ViewController: UIViewController, WKUIDelegate {
var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let myURL = URL(string:"https://someUrlToMyApp.appspot.com")
let myRequest = URLRequest(url: myURL!)
webView.load(myRequest)
if #available(iOS 11.0, *) {
webView.scrollView.contentInsetAdjustmentBehavior = .never;
}
webView.navigationDelegate = self
}
override func loadView() {
let webConfiguration = WKWebViewConfiguration()
webConfiguration.dataDetectorTypes = [.all]
webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.uiDelegate = self
view = webView
}
}
extension ViewController: WKNavigationDelegate {
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction,
decisionHandler: #escaping (WKNavigationActionPolicy) -> Void) {
guard
let url = navigationAction.request.url else {
decisionHandler(.cancel)
return
}
let string = url.absoluteString
if (string.contains("mailto:")) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
decisionHandler(.cancel)
return
}
decisionHandler(.allow)
}
}
One way to do what you want would be to implement WKNavigationDelegate:
import UIKit
import WebKit
class ViewController: UIViewController {
#IBOutlet weak var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
guard
let file = Bundle.main.path(forResource: "test", ofType: "html"),
let html = try? String(contentsOfFile: file) else {
return
}
webView.navigationDelegate = self
webView.loadHTMLString(html, baseURL: nil)
}
#IBAction func didTapButton(_ sender: Any) {
let email = "email#email.com"
guard
let url = URL(string: "mailto:\(email)") else {
return
}
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
}
extension ViewController: WKNavigationDelegate {
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction,
decisionHandler: #escaping (WKNavigationActionPolicy) -> Void) {
guard
let url = navigationAction.request.url,
let scheme = url.scheme else {
decisionHandler(.cancel)
return
}
if (scheme.lowercased() == "mailto") {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
// here I decide to .cancel, do as you wish
decisionHandler(.cancel)
return
}
decisionHandler(.allow)
}
}
Here you have a ViewController that has webView as an outlet, this WKWebView would load an html file like this:
Mail me
And I also added in storyboard a button just for reference, which would have the IBAction didTapButton described above.
The key here is:
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction,
decisionHandler: #escaping (WKNavigationActionPolicy) -> Void)
Which would give you the URL and let you decide what policy is suitable for it. Here I check if it contains mailto: as I already know this is what you're interested in so if it does, I simply open the URL as I would do if the user presses an UIButton visible on screen.
Hope it helps, cheers!
LE: Make sure you run on a real device (simulators don't have Mail app installed), also make sure you have the Mail app installed, cause I didn't..

How to fetch cookies values from WKWebView in Swift 4?

I'm not able to get cookies from this website - "https://bødekontrol.dk"
I'm using Xcode 9.4.1 and iOS 11.
I have followed below code,
import UIKit
import WebKit
class ViewController: UIViewController {
var urlString = "https://bødekontrol.dk"
var webView: WKWebView!
fileprivate var webViewIsInited = false
override func viewWillLayoutSubviews() {
if !webViewIsInited {
webViewIsInited = true
if webView == nil {
webView = WKWebView(frame: UIScreen.main.bounds, configuration: WKWebViewConfiguration())
}
view.addSubview(webView)
webView.navigationDelegate = self
webView.uiDelegate = self
webView.loadUrl(string: urlString)
}
}
}
extension ViewController: WKNavigationDelegate {
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: #escaping (WKNavigationResponsePolicy) -> Void) {
decisionHandler(.allow)
if let httpResponse = navigationResponse.response as? HTTPURLResponse {
if let headers = httpResponse.allHeaderFields as? [String: String], let url = httpResponse.url {
let cookies = HTTPCookie.cookies(withResponseHeaderFields: headers, for: url)
for cookie in cookies {
print(cookie.description)
print("found cookie " + cookie.name + " " + cookie.value)
}
}
}
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print("didFinish navigation")
}
}
extension ViewController: WKUIDelegate {
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
if navigationAction.targetFrame == nil {
let vc = ViewController()
vc.urlString = navigationAction.request.url?.absoluteString ?? "http://google.com"
vc.view.frame = UIScreen.main.bounds
vc.webView = WKWebView(frame: UIScreen.main.bounds, configuration: configuration)
navigationController?.pushViewController(vc, animated: false)
return vc.webView
}
return nil
}
}
extension WKWebView {
func loadUrl(string: String) {
if let encoded = string.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed),
let url = URL(string: encoded)
{
if self.url?.host == url.host {
self.reload()
} else {
load(URLRequest(url: url))
}
}
}
}
Implement this protocol WKHTTPCookieStoreObserver and check function of this protocol.
cookiesDidChange

How to add Activity Indicator to WKWebView (Swift 3)

I have a wkwebview in my app, and I want to add an activity indicator to it. I want it to where it appears when the webview is loading and disappears whenever it is finished loading, it disappears. Can you give me some code to do this? Here's my code right now:
#IBOutlet weak var Activity: UIActivityIndicatorView!
var webView : WKWebView!
#IBOutlet var containerView: UIView? = nil
override func viewDidLoad() {
super.viewDidLoad()
guard let url = URL(string: "http://ifunnyvlogger.wixsite.com/ifunnyvlogger/app-twitter") else { return }
webView = WKWebView(frame: self.view.frame)
webView.translatesAutoresizingMaskIntoConstraints = false
webView.isUserInteractionEnabled = true
webView.navigationDelegate = self
self.view.addSubview(self.webView)
let request = URLRequest(url: url)
webView.load(request)
}
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: #escaping (WKNavigationActionPolicy) -> Void) {
// Check if a link was clicked
if navigationAction.navigationType == .linkActivated {
// Verify the url
guard let url = navigationAction.request.url else { return }
let shared = UIApplication.shared
// Check if opening in Safari is allowd
if shared.canOpenURL(url) {
// Ask the user if they would like to open link in Safari
let alert = UIAlertController(title: "Do you want to open Safari?", message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Yes", style: .default, handler: { (alert: UIAlertAction) -> Void in
// User wants to open in Safari
shared.open(url, options: [:], completionHandler: nil)
}))
alert.addAction(UIAlertAction(title: "Opps, no.", style: .cancel, handler: nil))
present(alert, animated: true, completion: nil)
}
decisionHandler(.cancel)
}
decisionHandler(.allow)
}
func webViewDidStartLoad(_ : WKWebView) {
Activity.startAnimating()
}
func webViewDidFinishLoad(_ : WKWebView) {
Activity.startAnimating()
}
I'm creating an IOS app using xcode 8 and swift 3
Please, below code which is working fine.
#IBOutlet weak var Activity: UIActivityIndicatorView!
var webView : WKWebView!
#IBOutlet var containerView: UIView? = nil
override func viewDidLoad() {
super.viewDidLoad()
guard let url = URL(string: "http://www.facebook.com") else { return }
webView = WKWebView(frame: self.view.frame)
webView.translatesAutoresizingMaskIntoConstraints = false
webView.isUserInteractionEnabled = true
self.view.addSubview(self.webView)
let request = URLRequest(url: url)
webView.load(request)
// add activity
self.webView.addSubview(self.Activity)
self.Activity.startAnimating()
self.webView.navigationDelegate = self
self.Activity.hidesWhenStopped = true
}
Implement below these two delegate method:
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
Activity.stopAnimating()
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
Activity.stopAnimating()
}
Let me know if it is not working.
import UIKit
import WebKit
class ViewController: UIViewController, WKNavigationDelegate, WKUIDelegate {
var webView: WKWebView!
var activityIndicator: UIActivityIndicatorView!
override func viewDidLoad() {
webView = WKWebView(frame: CGRect.zero)
webView.navigationDelegate = self
webView.uiDelegate = self
view.addSubview(webView)
activityIndicator = UIActivityIndicatorView()
activityIndicator.center = self.view.center
activityIndicator.hidesWhenStopped = true
activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
view.addSubview(activityIndicator)
webView.load(URLRequest(url: URL(string: "http://google.com")!))
}
func showActivityIndicator(show: Bool) {
if show {
activityIndicator.startAnimating()
} else {
activityIndicator.stopAnimating()
}
}
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)
}
}
Swift 5 Version
The concept is simple enough to be ported to earlier swift versions.
This is a class we would use as a parent class anywhere we want a webview.
import UIKit
import WebKit
class CustomWebViewController: UIViewController, WKNavigationDelegate {
var activityIndicator: UIActivityIndicatorView!
override func viewDidLoad() {
super.viewDidLoad()
activityIndicator = UIActivityIndicatorView()
activityIndicator.center = self.view.center
activityIndicator.hidesWhenStopped = true
activityIndicator.style = .gray
activityIndicator.isHidden = true
view.addSubview(activityIndicator)
}
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
activityIndicator.isHidden = false
activityIndicator.startAnimating()
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
activityIndicator.stopAnimating()
activityIndicator.isHidden = true
}
}
If we have a UIViewController with a webview, we can just inherit from CustomWebViewController and it will take care of the rest for us. Remember to connect the webview IBOutlet.
import UIKit
import WebKit
class FirstViewController: CustomWebViewController {
#IBOutlet var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
webView.navigationDelegate = self
let url = URL(string: "https://google.com")
webView.load(URLRequest(url: url!))
}
}
In viewDidLoad you need to add the activityIndicator as a subView just as you did for your webView. Since it's an outlet, make sure the activityIndicator sits on top of your webView and you should be good to go. You also want to set activity.hidden to true when the webView stops loading.
It's also a good rule of thumb to lower case your 'Activity' outlet.
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(self.Activity)
guard let url = URL(string: "http://ifunnyvlogger.wixsite.com/ifunnyvlogger/app-twitter") else { return }
webView = WKWebView(frame: self.view.frame)
webView.translatesAutoresizingMaskIntoConstraints = false
webView.isUserInteractionEnabled = true
webView.navigationDelegate = self
self.view.addSubview(self.webView)
let request = URLRequest(url: url)
webView.load(request)
You also call activity.startAnimating in webViewDidFinishLoad(). Make sure you call activity.stopAnimating() when the webView finishes loading. Happy coding!
func webViewDidFinishLoad(_ : WKWebView) {
Activity.stopAnimating()
Activity.hidden = true
}
import UIKit
import WebKit
class ViewController: UIViewController, WKNavigationDelegate, WKUIDelegate {
var webView: WKWebView!
var activityIndicator: UIActivityIndicatorView!
override func viewDidLoad() {
webView = WKWebView(frame: CGRect.zero)
webView.navigationDelegate = self;
webView.uiDelegate = self
activityIndicator = UIActivityIndicatorView()
activityIndicator.hidesWhenStopped = true
activityIndicator.center = self.view.center
activityIndicator.style = UIActivityIndicatorView.Style.large
webView.addSubview(activityIndicator)
view = webView
let load_url = URL(string: "https://google.com/")!
webView.load(URLRequest(url: load_url))
activityIndicator.startAnimating()
let refresh = UIBarButtonItem(barButtonSystemItem: .refresh, target: webView, action: #selector(webView.reload))
toolbarItems = [refresh]
navigationController?.isToolbarHidden = false
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
title = webView.title
activityIndicator.stopAnimating()
}
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
activityIndicator.startAnimating()
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
activityIndicator.stopAnimating()
}
}
Please try the below code its working fine for me and please let me know if anything is wrong in it thanks in advance.
import UIKit
import WebKit
class WebViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {
#IBOutlet weak var contentView: UIView!
#IBOutlet weak var activityIndicatorView: UIActivityIndicatorView!
override func viewDidLoad() {
super.viewDidLoad()
setupView()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.setupWebView()
self.loadData()
}
fileprivate func setupView() {
self.contentView.isHidden = true
self.activityIndicatorView.startAnimating()
}
fileprivate func setupWebView() {
let webConfiguration = WKWebViewConfiguration()
webView = WKWebView(frame: contentView.bounds, configuration: webConfiguration)
webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.contentView.addSubview(webView)
self.webView.allowsBackForwardNavigationGestures = true
webView.uiDelegate = self
webView.navigationDelegate = self
}
fileprivate func loadData() {
if let url = URL(string: "http://google.com") {
/// For loading PDF content
if contentType == .pdf {
if let data = try? Data(contentsOf: url) {
self.webView.load(data, mimeType: "application/pdf", characterEncodingName: "", baseURL: url)
}
} else {
let request = URLRequest(url: url)
webView.load(request)
}
}
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
activityIndicatorView.stopAnimating()
self.contentView.isHidden = false
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
activityIndicatorView.stopAnimating()
}
}

Resources