UIRefreshControlを使ったPullToRefreshでrefreshのタイミングを変えたい


はじめに

を参考にしたUIRefreshControlに
addTarget(self, action: #selector(refresh), for: .valueChanged)
するやり方だとrefreshのタイミングに違和感があったので別のタイミングでrefreshを行いたかった

結論

UIScrollViewのdelegateの任意のタイミングでrefreshの処理を呼び出しましょう
個人的にはscrollViewWillEndDraggingかscrollViewWillBeginDeceleratingぐらいで
refreshするのがsafariやtwitterのPullToRefreshに近くてしっくりきました

class XXXViewController: UIViewController, UIScrollViewDelegate {
    
    @IBOutlet weak var webView: WKWebView! {
        didSet {
            webView.scrollView.delegate = self
            webView.scrollView.refreshControl = UIRefreshControl()
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    private func refresh() {
        reload()
    }
    
    private func didRefresh() {
        webView.scrollView.refreshControl?.endRefreshing()
    }
    
    // 指を離してスクロール位置が上まで戻った時
    func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) {
        guard let isRefreshing = webView.scrollView.refreshControl?.isRefreshing else { return }
        if isRefreshing {
            webView.refresh()
        }
    }
    
    // 指を離した時
    func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        guard let isRefreshing = webView.scrollView.refreshControl?.isRefreshing else { return }
        if isRefreshing {
            webView.refresh()
        }
    }
    
}

おまけ

addTargetするやり方も一応記載しておきます
下に引っ張ると閾値(50ptぐらい?)を超えたタイミングでrefreshが呼び出されます

class XXXViewController: UIViewController {
    @IBOutlet weak var webView: WKWebView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        webView.scrollView.refreshControl = UIRefreshControl()
        webView.scrollView.refreshControl?.addTarget(self, action: #selector(refresh), for: .valueChanged)
    }
    
    @objc
    private func refresh() {
        reload()
    }
    
    private func didRefresh() {
        webView.scrollView.refreshControl?.endRefreshing()
    }
    
}