1
votes

I'm using a UIRefreshControl to enable the pull-to-refresh gesture on a table view.

I have used the storyboard te setup the RefershControl and in my TableViewController is use the following code to bound the method to the RefeshControl:

self.refreshControl?.addTarget(self, action: Selector("getData"), forControlEvents: UIControlEvents.ValueChanged)

At the end of the getData() method I call the reloadData() method on the tableview and the stopRefreshing() method on the refreshcontrol.

This is working fine. I can pull to refresh and the table gets updated.

Next thing I want is to start the RefreshControl when the TableViewController gets loaded. To show the user that the app is getting the data. I tried to manually start the folowing code:

self.refreshCorntrol?.beginRefreshing()
getData()

It reloads the data but the animation is not working like it should. The table stays empty. Then when all the data is fetched the table is pulled down (like when I manually pull to refresh) en immediately pushed back up.

Anyone know if it is possible to change/fix this?

1

1 Answers

1
votes

Two things could be going on.

1. UI Updates must be dispatched on the main thread.

You're updating a tableView using it's .reloadData() method, which is considered an update to the UI. This being said, you must call .reloadData() on the main thread. While this should be done automatically for you already, I have run into some cases where I need to manually move it to the main thread. This can be done using

DispatchQueue.main.async {
  // Update UI ie. self.tableView.reloadData()
}

inside your function.

2. Programmatic pull refreshes don't always run for .valueChanged

It is important to call .valueChanged (or, as you have it in your code, UIControlEvents.ValueChanged) when you call the pull refresh function, so that it is aware of what you are refreshing for. When the user pull refreshes, your program already does it, in the forControlEvents segment of your refreshController declaration. However, when you call it manually from your code, it does not do this by default. Instead, you have to pass the action using sendActions. This can be done by using

self.refreshControl?.beginRefreshing()
self.refreshControl?.sendActions(for: UIControlEvents.ValueChanged)
getData()

to call the pull refresh, rather than just calling .beginRefreshing

Afterword

I ran into a similar issue a few days ago, and posted the question on Stack Overflow here (I'm providing attribution in case you can find your answer there, and because it is where I took my first solution for you from).