pull to refresh in webView using webkit in swift 4 - webview

I'm already add pull to refresh function in my code, the icon refresh will appear when I start pull it but when I had make changing in the webview such as tick the checkbox or enter the text in textbox,,why It not reset back to the default view?
import UIKit
import WebKit
class ViewController: UIViewController,WKNavigationDelegate,UIWebViewDelegate {
#IBOutlet weak var activityIndicator: UIActivityIndicatorView!
#IBOutlet weak var webView: WKWebView!
#IBOutlet var containerView: UIView? = nil
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(self.activityIndicator)
self.view.addSubview(self.webView)
let url:URL = URL(string : "https://www.facebook.com/")!
let urlRequest : URLRequest = URLRequest(url: url)
webView.load(urlRequest)
//activity indicator
self.webView.addSubview(self.activityIndicator)
self.activityIndicator.startAnimating()
self.webView.navigationDelegate = self
self.activityIndicator.hidesWhenStopped = true
self.webView.navigationDelegate=self;
//refresh
webView.scrollView.bounces = true
let refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: #selector(ViewController.refreshWebView), for: UIControlEvents.valueChanged)
webView.scrollView.addSubview(refreshControl)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear( animated )
let url:URL = URL(string : "https://www.facebook.com/")!
let urlRequest : URLRequest = URLRequest(url: url)
webView.load(urlRequest)
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
activityIndicator.stopAnimating()
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
activityIndicator.stopAnimating()
}
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
activityIndicator.startAnimating()
}
#objc func refreshWebView(sender: UIRefreshControl) {
print("refersh")
//
sender.endRefreshing()
}
}

EDIT: I found a solution how the pull to refresh Indicator waits til the WebView did Finish loading:
I have used a UIRefreshControl instead an UIActivityIndicator.
import UIKit
import WebKit
class ViewController: UIViewController,WKNavigationDelegate,UIWebViewDelegate {
#IBOutlet weak var webView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
let url:URL = URL(string : "https://www.google.com")!
let urlRequest : URLRequest = URLRequest(url: url)
webView.loadRequest(urlRequest)
//refresh
webView.scrollView.alwaysBounceVertical = true
let refreshControl = UIRefreshControl()
refreshControl.tintColor = .white
let attributes = [NSForegroundColorAttributeName: UIColor.white]
let attributedTitle = NSAttributedString(string: "refreshing ...", attributes: attributes)
refreshControl.attributedTitle = attributedTitle
refreshControl.addTarget(self, action: #selector(ViewController.refreshWebView), for: UIControlEvents.valueChanged)
refreshControl.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
webView.scrollView.refreshControl = refreshControl
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear( animated )
let url:URL = URL(string : "https://www.google.com")!
let urlRequest : URLRequest = URLRequest(url: url)
webView.loadRequest(urlRequest)
}
func webViewDidFinishLoad(_ webView: UIWebView) {
self.webView.scrollView.refreshControl?.endRefreshing()
}
func webView(_ webView: UIWebView, didFailLoadWithError error: Error) {
self.webView.scrollView.refreshControl?.endRefreshing()
}
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
return true
}
#objc func refreshWebView(sender: UIRefreshControl) {
print("refresh")
self.webView.reload()
}

Related

create activity indicator when navigate in webView using webkit in swift 4

I want to create a wkwebview in my iOS app, and I want to add an activity indicator to it. I want when we click all the button or part in the webview, it will appear the activity indicator. Can you give me some code to do this? Here's my code right now. It only show the indicator when start load the website but when we click at the process, the indicator not appear.
import UIKit
import WebKit
class ViewController: UIViewController,WKNavigationDelegate,UIWebViewDelegate {
#IBOutlet weak var activityIndicator: UIActivityIndicatorView!
#IBOutlet weak var webView: WKWebView!
#IBOutlet var containerView: UIView? = nil
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(self.activityIndicator)
self.view.addSubview(self.webView)
let url:URL = URL(string : "https://www.facebook.com/")!
let urlRequest : URLRequest = URLRequest(url: url)
webView.load(urlRequest)
//activity indicator
self.webView.addSubview(self.activityIndicator)
self.activityIndicator.startAnimating()
self.webView.navigationDelegate = self
self.activityIndicator.hidesWhenStopped = true
//refresh
webView.scrollView.bounces = true
let refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: #selector(ViewController.refreshWebView), for: UIControlEvents.valueChanged)
webView.scrollView.addSubview(refreshControl)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear( animated )
let url:URL = URL(string : "https://www.facebook.com/")!
let urlRequest : URLRequest = URLRequest(url: url)
webView.load(urlRequest)
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
activityIndicator.stopAnimating()
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
activityIndicator.stopAnimating()
}
#objc func refreshWebView(sender: UIRefreshControl) {
print("refersh")
sender.endRefreshing()
}
}
Below code will help to add activity indicator in Navigation Bar. So no need to create any subviews. This works with Swift 4.
import Foundation
import UIKit
import WebKit
class ContactVC: UIViewController, WKNavigationDelegate {
var webView: WKWebView!
var activityIndicator: UIActivityIndicatorView!
override func loadView() {
webView = WKWebView()
webView.navigationDelegate = self
view = webView
activityIndicator = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 20, height: 20))
activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
activityIndicator.hidesWhenStopped = true
let barButton = UIBarButtonItem(customView: activityIndicator)
self.navigationItem.setRightBarButton(barButton, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: "https://www.facebook.com/")!
webView.load(URLRequest(url: url))
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func showActivityIndicator(show: Bool) {
if show {
// Start the loading animation
activityIndicator.startAnimating()
} else {
// Stop the loading animation
activityIndicator.stopAnimating()
}
}
//MARK:- WKNavigationDelegate
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
print("Start to load")
showActivityIndicator(show: true)
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print("Finish to load")
title = webView.title
showActivityIndicator(show: false)
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
print(error.localizedDescription)
showActivityIndicator(show: false)
}
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
print(error.localizedDescription)
showActivityIndicator(show: false)
}
}
Implement didStartProvisionalNavigation delegate function.
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
activityIndicator.startAnimating()
}

How to add UIActivityIndicatorView to WKWebView?

I'm new to Swift and I need some help implementing the UIActivityInidicatorView to WKWebView. It should appear while the webpage is loading and disappear when the website finished loading.
Here is my code so far:
import UIKit
import WebKit
class ViewController: UIViewController {
#IBOutlet weak var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let myURL = URL(string: "https://www.google.com")
let myRequest = URLRequest(url: myURL!)
webView.load(myRequest)
}
}
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)
}
}
I finally got it working like this:
import UIKit
import WebKit
class ViewController: UIViewController, WKNavigationDelegate {
#IBOutlet weak var webView: WKWebView!
#IBOutlet weak var ActivityIndicator: UIActivityIndicatorView!
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
ActivityIndicator.stopAnimating()
}
override func viewDidLoad() {
super.viewDidLoad()
let myURL = URL(string: "https://www.google.com/")
let myRequest = URLRequest(url: myURL!)
webView.navigationDelegate = self
webView.load(myRequest)
}
}
Try this i hope this will help you
import UIKit
import WebKit
class ViewController: UIViewController, WKNavigationDelegate {
#IBOutlet weak var webView: WKWebView!
#IBOutlet weak var ActivityIndicator: UIActivityIndicatorView!
override func viewDidLoad() {
super.viewDidLoad()
let myURL = URL(string: "https://www.google.com")
let myRequest = URLRequest(url: myURL!)
webView.navigationDelegate = self
webView.load(myRequest)
}
func webView(_ webView: WKWebView,didStart navigation: WKNavigation!) {
print("Start Page Loading")
ActivityIndicator.statAnimating()
}
func webView(_ webView: WKWebView,didFinish navigation: WKNavigation!) {
print("Page loaded")
ActivityIndicator.stopAnimating()
}
}

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

How do I add Pull to Refresh in WebView?

I'm very new to developing. I'm building a WebView and I want it to have pull to refresh capabilities. How do I go about doing that in swift?
My code in the View Controller is
#IBOutlet var webView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
func webViewDidFinishLoad(webView: UIWebView) {
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
}
func webViewDidStartLoad(webView: UIWebView) {
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
}
let url = NSURL (string: "https://www.foo.com");
let requestObj = NSURLRequest(URL: url!);
webView.loadRequest(requestObj);
NSUserDefaults.standardUserDefaults().registerDefaults(["UserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/601.5.17 (KHTML, like Gecko) Version/9.1 Safari/601.5.17"])
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
Your code is buggy you added two Web view Delegate in side the ViewDidLoad method that must be following and check the following viewDidLoad code for adding Pull to Refresh in web view:
#IBOutlet var webView: UIWebView!
var refController:UIRefreshControl = UIRefreshControl()
override func viewDidLoad() {
super.viewDidLoad()
let url = NSURL (string: "https://www.foo.com");
let requestObj = NSURLRequest(URL: url!);
webView.loadRequest(requestObj);
NSUserDefaults.standardUserDefaults().registerDefaults(["UserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/601.5.17 (KHTML, like Gecko) Version/9.1 Safari/601.5.17"])
refController.bounds = CGRectMake(0, 50, refController.bounds.size.width, refController.bounds.size.height)
refController.addTarget(self, action: Selector("mymethodforref:"), forControlEvents: UIControlEvents.ValueChanged)
refController.attributedTitle = NSAttributedString(string: "Pull to refresh")
webView.scrollView.addSubview(refController)
}
func mymethodforref(refresh:UIRefreshControl){
webView.reload()
refController.endRefreshing()
}
func webViewDidFinishLoad(webView: UIWebView) {
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
}
func webViewDidStartLoad(webView: UIWebView) {
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
Details
Xcode 11.3.1, Swift 5.1
Solution
extension WKWebView {
var refreshControl: UIRefreshControl? { (scrollView.getAllSubviews() as [UIRefreshControl]).first }
enum PullToRefreshType {
case none
case embed
case custom(target: Any, selector: Selector)
}
func setPullToRefresh(type: PullToRefreshType) {
(scrollView.getAllSubviews() as [UIRefreshControl]).forEach { $0.removeFromSuperview() }
switch type {
case .none: break
case .embed: _setPullToRefresh(target: self, selector: #selector(webViewPullToRefreshHandler(source:)))
case .custom(let params): _setPullToRefresh(target: params.target, selector: params.selector)
}
}
private func _setPullToRefresh(target: Any, selector: Selector) {
let refreshControl = UIRefreshControl()
refreshControl.addTarget(target, action: selector, for: .valueChanged)
scrollView.addSubview(refreshControl)
}
#objc func webViewPullToRefreshHandler(source: UIRefreshControl) {
guard let url = self.url else { source.endRefreshing(); return }
load(URLRequest(url: url))
}
}
// https://stackoverflow.com/a/47282118/4488252
extension UIView {
class func getAllSubviews<T: UIView>(from parenView: UIView) -> [T] {
return parenView.subviews.flatMap { subView -> [T] in
var result = getAllSubviews(from: subView) as [T]
if let view = subView as? T { result.append(view) }
return result
}
}
func getAllSubviews<T: UIView>() -> [T] { return UIView.getAllSubviews(from: self) as [T] }
}
Usage
Setup
import UIKit
import WebKit
class ViewController2: UIViewController {
private weak var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
// ... create webView here
webView.navigationDelegate = self
}
}
// MARK: WKNavigationDelegate
extension ViewController2: WKNavigationDelegate {
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
webView.refreshControl?.endRefreshing()
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
webView.refreshControl?.endRefreshing()
}
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
webView.refreshControl?.endRefreshing()
}
}
Activate pull to refresh (option 1)
webView.setPullToRefresh(type: .embed)
Activate pull to refresh (option 2)
#objc func customPullToRefreshHandler(source: UIRefreshControl) {
guard let url = webView.url else { source.endRefreshing(); return }
webView.load(URLRequest(url: url))
}
// ....
webView.setPullToRefresh(type: .custom(target: self, selector: #selector(customPullToRefreshHandler(source:))))
Deactivate pull to refresh
webView.setPullToRefresh(type: .none)
Full sample
Do not forget to paste here the solution code
import UIKit
import WebKit
class ViewController: UIViewController {
private weak var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
createWebView()
webView.load("https://google.com")
// Way 1
webView.setPullToRefresh(type: .embed)
// Way 2
// webView.setPullToRefresh(type: .custom(target: self, selector: #selector(customPullToRefreshHandler(source:))))
}
private func createWebView() {
let webView = WKWebView(frame: .zero, configuration: .init())
view.addSubview(webView)
webView.navigationDelegate = self
self.webView = webView
webView.translatesAutoresizingMaskIntoConstraints = false
webView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
webView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
view.bottomAnchor.constraint(equalTo: webView.bottomAnchor).isActive = true
view.rightAnchor.constraint(equalTo: webView.rightAnchor).isActive = true
}
// #objc func customPullToRefreshHandler(source: UIRefreshControl) {
// guard let url = webView.url else { source.endRefreshing(); return }
// webView.load(URLRequest(url: url))
// print("WebView started loading")
// }
}
// MARK: WKNavigationDelegate
extension ViewController: WKNavigationDelegate {
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
webView.refreshControl?.endRefreshing()
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
webView.refreshControl?.endRefreshing()
}
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
webView.refreshControl?.endRefreshing()
}
}
extension WKWebView {
func load(_ urlString: String) {
guard let url = URL(string: urlString) else { return }
load(URLRequest(url: url))
}
}
Following code will put the refresh control in scrollview of webview.Initially it will load google.com. To see pull to refresh clearly I have set white color to the background of scroll view so it is clearly visible and on pull to refresh webview opens facebook page.
class ViewController: UIViewController,UIWebViewDelegate {
#IBOutlet weak var webView: UIWebView!
var refreshControl:UIRefreshControl?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.refreshControl = UIRefreshControl.init()
refreshControl!.addTarget(self, action:#selector(refreshControlClicked), for: UIControlEvents.valueChanged)
self.webView.scrollView.addSubview(self.refreshControl!)
self.webView.scrollView.backgroundColor = UIColor.white
self.webView.delegate = self
let url:URL = URL.init(string:"https://www.google.com")!
self.loadRequestWithUrl(URLRequest.init(url: url))
}
func webViewDidStartLoad(_ webView: UIWebView) {
NSLog("website loaded")
}
func loadRequestWithUrl(_ urlRequest : URLRequest?){
if(urlRequest != nil){
self.webView.loadRequest(urlRequest!)
}
}
func refreshControlClicked(){
let url:URL = URL.init(string:"https://www.facebook.com")!
self.loadRequestWithUrl(URLRequest.init(url: url))
}
}
You can use this one
Write this in DidLoad method
webViewHome.scrollView.delegate = self;
And then write this method
#pragma mark Scrollview delegate
(void)scrollViewWillEndDragging:(UIScrollView *)scrollView
withVelocity:(CGPoint)velocity
targetContentOffset:(inout CGPoint *)targetContentOffset{
if (scrollView.contentOffset.y < 0){
DLog(#" webview on top ");
[self AgainCheckInternet:nil];
}
}
Note: Please make sure you didn't set scrollview bounces property to No otherwise this method will not call

Displaying activity indicator on WKWebView using swift

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

Resources