如何在 WebView 中添加 Pull to Refresh?

How do I add Pull to Refresh in WebView?

我对开发还很陌生。我正在构建一个 WebView,我希望它具有刷新功能。我如何在 swift 中做到这一点?

我在视图控制器中的代码是

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

}

您的代码有问题,您在必须遵循的 ViewDidLoad 方法中添加了两个 Web 视图委托,并检查以下 viewDidLoad 代码以在 Web 视图中添加 Pull to Refresh:

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

    }

}

以下代码会将刷新控件放在 webview.Initially 的滚动视图中,它将加载 google.com。为了清楚地看到拉动刷新,我将滚动视图的背景设置为白色,这样它就清晰可见,拉动刷新 webview 打开 facebook 页面。

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

你可以用这个

  1. 在DidLoad方法中写这个

    webViewHome.scrollView.delegate = self; 
    

    然后写这个方法

    #pragma mark Scrollview 委托

    • (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)速度 targetContentOffset:(inout CGPoint *)targetContentOffset{ 如果(scrollView.contentOffset.y < 0){ DLog(@"网页视图在顶部"); [自我AgainCheckInternet:nil]; } }

注意:请确保您没有将 scrollview bounces 属性 设置为 No 否则此方法将不会调用

详情

  • Xcode11.3.1,Swift5.1

解决方案

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 { [=10=].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))
    }
}

// 

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] }
}

用法

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)

完整样本

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