iOS

Better Code: Implement Pull to Refresh in your iOS Apps

A pull-to-refresh gesture provides a very pleasant interaction and gives sophisticated look to a table-based app.

1_pull_to_refresh.PNG
You've no doubt used at least one app, such as the iOS mail app, that uses a pull-to-refresh gesture to refresh a UITableview. It provides a very pleasant interaction and gives a cool, sophisticated look to a table-based app. It also saves space and reduces clutter in the app's UI, since space no longer need be reserved for a toolbar and refresh button.

Prior to iOS 6, adding this kind of functionality to your own app was truly a nontrivial task requiring a lot of time and effort. As we'll see, adding pull-to-refresh using the UIRefreshControl class in iOS6 is literally a snap. We'll use a small project to demonstrate just how quickly you can add this functionality to your own apps in just a few minutes.

RefreshMe

To keep things simple and focus only on what's necessary to implement the refresh control, we'll modify a project that I've already created for you, which you can download for free. <insert download link>

Download the RefreshMe project, open it in Xcode, and click on ViewController.m. RefreshMe is a trivial table-based app that displays a list random numbers and regenerates them whenever we refresh the table. The screenshots below show the different views of UIRefreshControl as the user pulls and then releases the control.

a_skantner_pull_to_refresh.png

b_skantner_pull_to_refresh.png

Note in our app that ViewController is a subclass of UITableViewController. This is required in order to use the refreshControl property that is now part of table view controllers in iOS6.  

Adding the Refresh Control

Modify viewDidLoad by adding the code shown below.

- (void)viewDidLoad

{

  [super viewDidLoad];

  UIRefreshControl *refresh = [[UIRefreshControl alloc] init];

  refresh.attributedTitle = [[NSAttributedString alloc] initWithString:@"Pull to Refresh"];

 

  [refresh addTarget:self action:@selector(crunchNumbers)

  forControlEvents:UIControlEventValueChanged];

 

  self.refreshControl = refresh;

 

  testNumbers = [[NSMutableArray alloc] init];

  [self crunchNumbers];

 

}

In the code above, we allocate a new UIRefreshControl object, set its title, and then add an action that will execute our crunchNumbers method whenever the user pulls to refresh. Note that self.refreshControl is a property of the UITableView, and all we have to do to enable the pull-to-refresh behavior is to set this property to our newly-created refresh object. Yes, indeed, it was that simple! Now with pull-to-refresh functionality added to our table, we can move on to care for just a few other details.

Once the refresh animation is started, it will continue to run until we stop it, so let's add a stopRefresh: method as shown below directly under viewDidLoad:

- (void)stopRefresh

{

  [self.refreshControl endRefreshing];

}

The endRefreshing method on UIRefreshControl stops the animation and hides the control until we refresh the table again. The remaining detail is to call stopRefresh after the table data is regenerated, so we'll add the following line in bold to the crunchNumbers method:

- (void)crunchNumbers

{

  [testNumbers removeAllObjects];

  for (int i = 0; i 

Note that we don't have to call reloadData as we normally would on the table view because the refresh control handles that for us. And because our method regenerates the data so quickly, we use performSelector:withObject:afterDelay: to delay the execution of stopRefresh for 2.5 seconds so that we enough time to observe the animation.

Build and run the project (Shortcut: press Cmd+R) and pull down on the table. Note that the refresh will not fire until the control is pulled past a certain point.

Congratulations! You are now certified to implement pull-to-refresh in your apps!

Bottom line

If there is any downside of pull-to-refresh, it would be that it could possibly be considered not easily discoverable by the user. In other words, the feeling among some developers and designers is that users won't realize they can pull down on a table, and if anything, will only discover the pull-to-refresh feature by accident. At this point however, with almost a year of iOS6 experience under everyone's belts, there is much more awareness of the pull down gesture in both the user and developer community, and it seems unlikely to generate as much confusion (or support questions!) as it may have in the past.

So if you've been putting off adding pull-to-refresh to your apps, wait no longer! It's quick, it's easy, and it adds some delightful interaction to your apps.

About

Scott Kantner started his IT career on a Radio Shack TRS-80 model I back in 1978. He is CTO of a hosting/colocation firm, a tech writer, and an avid iOS app developer. He has several music-related apps in the App Store that you can learn about at OnS...

4 comments
souleiman
souleiman

Thanks for the nice tutorial. One thing I noticed - instead of having a dedicated stopRefresh method, you can simply do this in crunchNumbers:

[self.refreshControl performSelector:@selector(endRefreshing)];

Good luck everyone!

RachnaAnil
RachnaAnil

Works great.

You could also mention what should be done if the base class is not UITableViewController in which case we cannot access the self.refreshControl property directly

mobilesite
mobilesite

Refresh me - I like it. A real good project like this one should not go waste. I am sure iOS developers are aware of misuse of iPhone apps worldwide.

guillegr123
guillegr123

Good evening! The link for download the project is missing.