10

I'm trying to add pull to Refresh to WKWebView. Where in this code would I add something that would allow me to trigger pull to refresh? I haven't found any viable ways to add it to my code so you won't find any attempts by me to accomplish this in the code below. Most answers that I've found are in Objective-C or a language unsupported by my project.

import UIKit
import WebKit

class CycleViewController: UIViewController, WKNavigationDelegate, WKUIDelegate {

    var webView: WKWebView!
    @IBOutlet weak var containerView: UIView!
    @IBOutlet weak var progressView: UIProgressView!

    override func loadView() {
        super.loadView()
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        progressView.setProgress(0.1, animated: true)

        let webConfiguration = WKWebViewConfiguration()
        webConfiguration.applicationNameForUserAgent = "Version/8.0.2 Safari/600.2.5"

        let customFrame = CGRect.init(origin: CGPoint.zero, size: CGSize.init(width: 0.0, height: self.containerView.frame.size.height))

        webView = WKWebView(frame: customFrame, configuration: webConfiguration)
        webView.uiDelegate = self
        webView.navigationDelegate = self
        self.containerView.addSubview(webView)
        self.webView.translatesAutoresizingMaskIntoConstraints = false

        self.view.addConstraint(NSLayoutConstraint(item: webView, attribute: .trailing, relatedBy: .equal, toItem: self.containerView, attribute: .trailing, multiplier: 1, constant: 0))
        self.view.addConstraint(NSLayoutConstraint(item: webView, attribute: .leading, relatedBy: .equal, toItem: self.containerView, attribute: .leading, multiplier: 1, constant: 0))
        self.view.addConstraint(NSLayoutConstraint(item: webView, attribute: .top, relatedBy: .equal, toItem: self.containerView, attribute: .top, multiplier: 1, constant: 0))
        self.view.addConstraint(NSLayoutConstraint(item: webView, attribute: .bottom, relatedBy: .equal, toItem: self.containerView, attribute: .bottom, multiplier: 1, constant: 0))



        progressView.sizeToFit()
        progressView.progressTintColor = UIColor(red: 255/255, green: 204/255, blue: 0/255, alpha: 1.0)

        webView.backgroundColor = UIColor.clear
        webView.backgroundColor = UIColor(red: 0.0196, green: 0.4, blue: 0.2902, alpha: 1.0)
        webView.isOpaque = false

        self.webView.load(NSURLRequest(url: URL(string: "https://jwelsh19.wixsite.com/countryday")!) as URLRequest)

        self.webView.addObserver(self, forKeyPath: "estimatedProgress", options: .new, context: nil)

    }

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if keyPath == "estimatedProgress" {
            print(self.webView.estimatedProgress);
            self.progressView.progress = Float(self.webView.estimatedProgress);        }
    }

    @IBAction func home(_ sender: UIButton) {
        let myURL = URL(string: "https://jwelsh19.wixsite.com/countryday")
        let myRequest = URLRequest(url: myURL!)
        webView.load(myRequest)
    }

    @IBAction func refresh(_ sender: UIButton) {

        webView.reload()

    }

    //This method will call when you press button.
    @objc func acButtonPressed() {

        print("button is pressed")
        self.performSegue(withIdentifier: "Account", sender: self)
    }
}
`
rmaddy
  • 314,917
  • 42
  • 532
  • 579
Nigel
  • 103
  • 1
  • 4
  • What's wrong with the Objective-C code you've found? It's the same APIs used by Swift. Just translate the code as needed using the APIs as a guideline. – rmaddy Nov 12 '18 at 18:55

3 Answers3

20

Nothing special about applying pull to refresh behavior to a web view, however keep in mind that you would need to add the UIRefreshControl as a subview into the web view scrollView:

override func viewDidLoad() {
    // after done with setup the `webView`:
    let refreshControl = UIRefreshControl()
    refreshControl.addTarget(self, action: #selector(reloadWebView(_:)), for: .valueChanged)
    webView.scrollView.addSubview(refreshControl)
}

reloadWebView method:

@objc func reloadWebView(_ sender: UIRefreshControl) {
    webView.reload()
    sender.endRefreshing()
}

Tip: instead of using NSURLRequest and casting it to URLRequest you could use URLRequest directly, so instead of:

self.webView.load(NSURLRequest(url: URL(string: "https://jwelsh19.wixsite.com/countryday")!) as URLRequest)

do it as:

webView.load(URLRequest(url: URL(string: "https://jwelsh19.wixsite.com/countryday")!))
Ahmad F
  • 30,560
  • 17
  • 97
  • 143
6

Add refreshControl to webView.scrollView under didSet callback to webView

var webView: WKWebView! {
    didSet {
        let refreshControl = UIRefreshControl()
        refreshControl.addTarget(self, action: #selector(reload(_:)), for: .valueChanged)
        webView.scrollView.refreshControl = refreshControl
    }
}

And add this to reload webView

@objc private func reload(_ refreshControl: UIRefreshControl) {
    refreshControl.endRefreshing()
    webView.reload()
}
Satish
  • 2,015
  • 1
  • 14
  • 22
0

The above answer is correct but to use UIRefreshControl you need to be turned on scrollView.bounces = true. So the fresh code will be:

webView.scrollView.bounces = true
let refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: #selector(ViewController.refreshWebView), for: UIControlEvents.valueChanged)
webView.scrollView.addSubview(refreshControl)

After that separate function:

func refreshWebView(sender: UIRefreshControl) {
    webView.reload()
    sender.endRefreshing()
}
Md Imran Choudhury
  • 9,343
  • 4
  • 62
  • 60
  • At least as of today, webView.scrollView.bounces = true by default. But Apple can always change that ;) – Dima G Apr 20 '20 at 07:59