6

I have a UITableViewController with the built-in UIRefreshControl. I have two issues with the refresh animation which I want to fix.

  1. When I drag and pull the table view, it starts to update data from our server. If the user keeps it dragging, a noticeable offset jump occurs.

  2. When the refresh operation ends, the table view hides the refresh control animated. After it finishes hiding it, the control flashes for a a few frames.

Showcase

The control is set up from UIStoryboard. I set up target and tint color from there. When the action fires my code refreshes the data from our server, which has a callback when the server responds. I stop the refresh control from there:

dispatch_async(dispatch_get_main_queue(), ^{
   [self.refreshControl endRefreshing];
});
...
[self.tableView reloadData];

Is something I do wrong or UIRefreshControl is just buggy in iOS 11?

gklka
  • 2,459
  • 1
  • 26
  • 53
  • reload tableView in dispatch_async method – Chirag Kothiya Jun 28 '18 at 09:40
  • That makes things even worse. UIRefreshControl completely skips animating and a wrong offset is being set to the table view if I use that way. – gklka Jun 28 '18 at 09:50
  • Can you please try to add `self.extendedLayoutIncludesOpaqueBars = YES` to your controller ? `UIRefreshControl` has a lot of issues like this… – AnthoPak Jun 28 '18 at 10:49
  • I never hit this kind of behavior when dealing with `UIRefreshControl` & async network requests. So I guess there is bug some where in your code. – RyanB Jun 28 '18 at 10:58
  • When I move the `-endRefreshing` call after `-reloadData`, the flashing problem disappears. The jumping while dragging is caused by the reloading it seems. How else can I reload? – gklka Jun 28 '18 at 11:03

2 Answers2

10

I was experiencing a similar issue and this is how I finally fixed it:

  1. The 'estimated row height' property needs to be set. Otherwise, reloadData() causes a noticeable jump. This is explained here

  2. Calling endRefreshing() while the user is still dragging also results in a noticeable jump. To avoid this:

    • When I receive new data from the server, I check if the user is still dragging (UIScrollView.isDragging). If this is the case then I don't call endRefreshing() immediately, but set a flag instead.
    • I override scrollViewDidEndDragging and check the flag there; if set, then I call endRefreshing() and clear the flag.
Grodriguez
  • 21,501
  • 10
  • 63
  • 107
4

The UIRefreshControl is kind of mysterious at this point (it is affected by many things - do you use large titles, set the refreshControl in viewDidLoad or elsewhere etc.)

The best way to get rid of these issues is to stop observing valueChanged of the UIRefreshControl and do reloadData / endRefreshing after you're sure there is no dragging (e.g. scrollViewDidEndDragging).

Also I was able to reproduce the activity indicator flickering of UIRefreshControl from your gif this way (and only for iPhone X-like devices with no navigation bar translucency):

edgesForExtendedLayout = [.top]
extendedLayoutIncludesOpaqueBars = true

then all I had to do was changing the edgesForExtendedLayout and extendedLayoutIncludesOpaqueBars.

Jakub Truhlář
  • 20,070
  • 9
  • 74
  • 84