Search code examples
iosswiftuitableviewrefreshuirefreshcontrol

TableView with UIRefreshControl seems to glitch a bit when reloading?


I have a table view inside a container. When a user swipes down to refresh I notice that the cells instantly pop back to the top. It looks very buggy.

func setupRefresh() {
    //        refreshControl.attributedTitle = NSAttributedString(string: "")
    refreshControl.addTarget(self, action: #selector(refresh(_:)), for: UIControl.Event.valueChanged)
    tableView.insertSubview(refreshControl, at: 0)
    //tableView.addSubview(refreshControl) // not required when using UITableViewController
}

@objc func refresh(_ sender:AnyObject) {
    // Code to refresh table view
    print("Refreshing...")
    tableView.isScrollEnabled = false
    array.removeAll()
    items = 0
    number = 0
    getRecentNotifs(limit: 10)
    //        refreshControl.endRefreshing()
    //        tableView.isScrollEnabled = true
    //        tableView.isUserInteractionEnabled = true
}

Then within my fetch method, I do this. I also tried doing this inside of the refresh and that failed, yielding the same results

dispatchGroup.notify(queue: .main, execute: {
    if true {
        if !self.tableView.isScrollEnabled {
            self.refreshControl.endRefreshing()
            self.tableView.isScrollEnabled = true
        }

        self.tableView.reloadData()
    }
})

I have looked here and many more places with no success.

A very bad fix to this could be:

 ...
Timer.scheduledTimer(timeInterval: 0.8, target: self, selector: #selector(self.delayedAction), userInfo: nil, repeats: false)
}

@objc func delayedAction() {
    refreshControl.endRefreshing()
}

Solution

  • Move the refreshControl.endRefreshing() into the completion handler of the function you are getting the data from.

    Example:

    func getRecentNotifs(limit: Int) {
    
         // Get Data ...
    
         Network.getData(limit: limit) { (data, error) in   // Completion Block
    
              // Update Table View
              self.tableView.reloadData()
    
              // End Refresh Control
              self.refreshControl.endRefreshing()
              self.activityIndicatorView.stopAnimating()
    
         })
    
    }
    

    You were calling refreshControl.endRefreshing() in the refresh control's target method, so it was ending right away.