0
votes

I've a VC containing Table View. I've implemented pull to refresh on table view and activity indicator on view. On pull to refresh table view flickers as it looks like it has finished refreshing and reloads while I pull down and keep holding the table view. I'm not sure where it's going wrong. Following is my code. How to I implement it correctly?

class MyViewController: CustomVC {

    override func viewDidLoad() {
        super.viewDidLoad()

        self.addRefreshControl(to: tableView)
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(true)

        self.view.activityStartAnimating()
        self.tableView.isHidden = true
        loadContent(isRefresh: false)
    }

    private func loadContent(isRefresh: Bool) {

         fetchContent() { (result, error) in

            // ....
            if isRefresh {
                self.refreshControl.endRefreshing()
            } else {
                self.view.activityStopAnimating()
            }

            // ...
            self.tableView.reloadData()
            self.tableView.isHidden = false
        }
    }

    // Pull to refresh
    override func fetchDataForRefresh() {
        loadContent(isRefresh: true)
    }
}

Custom VC class

class CustomVC: UIViewController {

    lazy var refreshControl: UIRefreshControl = {
       let refreshControl = UIRefreshControl()
        refreshControl.addTarget(self, action: #selector(refresh(_:)), for: UIControl.Event.valueChanged)
        refreshControl.transform = CGAffineTransform(scaleX: 0.87, y: 0.87)
        return refreshControl
    }()

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

    func addRefreshControl(to tableView: UITableView) {
        if #available(iOS 10.0, *) {
            tableView.refreshControl = refreshControl
        } else {
            tableView.addSubview(refreshControl)
        }

        tableView.indicatorStyle = .white
    }

    @objc func refresh(_ refreshControl: UIRefreshControl) {
        fetchDataForRefresh()
    }

    func fetchDataForRefresh() {
    }
}

Fetch Content

func fetchContent() {
    // .....
    DispatchQueue.main.async {
        completed(resultData,nil)
        return
    }
    //....
}
1

1 Answers

0
votes

Try this technique

 func setupRefreshControl() {
    refreshControl = UIRefreshControl()
    refreshControl?.addTarget(self, action: #selector(refreshData), for: .valueChanged)
    tableView?.refreshControl = refreshControl
}

When you finished fetching your data:

DispatchQueue.main.async {   
self.refreshControl?.perform(#selector(UIRefreshControl.endRefreshing), with: nil, afterDelay: 0)
self.tableView.reloadData()
}

Please note I have access to refreshControl because I'm inside a UITableViewController but you can easily add it in a UIViewController as well.

Remove the if refresh else ... from your code and put your reload your UITableView and endRefreshing on the main thread as I mentioned above