4.10. Displaying a Refresh Control for Table Views


You want to display a nice refresh UI control on top of your table views that allows your users to intuitively pull down the table view in order to update its contents. An example of a refresh control is shown in Figure 4-24.

A refresh control is displayed on top of a table view

Figure 4-24. A refresh control is displayed on top of a table view


Simply create a table view controller (as discussed in Recipe 4.9) and set its refreshControl property to a new instance of UIRefreshControl class, as shown here:

- (id)initWithStyle:(UITableViewStyle)style{
    self = [super initWithStyle:style];
    if (self) {

        [self.tableView registerClass:[UITableViewCell class]

        self.allTimes = [NSMutableArray arrayWithObject:[NSDate date]];

        /* Create the refresh control */
        self.refreshControl = [[UIRefreshControl alloc] init];
        self.refreshControl = self.refreshControl;
        [self.refreshControl addTarget:self

    return self;


Refresh controls are simple visual indicators that appear on top of table views and tell the user that something is about to get updated. For instance, prior to iOS 6, in order to refresh your mailbox in the Mail app, you had to press a refresh button. In the new iOS, now you can simply drag the list of your emails down, as if you wanted to see what’s above there in the list that you haven’t read already. Once iOS detects this gesture of yours, it will trigger a refresh. Isn’t that cool? Twitter’s iPhone app started this whole thing when they added a refresh control to their apps, so kudos to them for this. Apple has realized that this is in fact a really nice and intuitive way of updating table views and has since added a dedicated component to the SDK to implement it. The class name for this component is UIRefreshControl.

Create a new instance of this class simply by calling its init method. Once you are done, add this instance to your table view controller, as described in the Solution section of this recipe.

Now you’ll want to know when the user has triggered a refresh on your table view. To do this, simply call the addTarget:action:forControlEvents: instance method of your refresh control and pass the target object and a selector on that object that takes care of the refresh for you. Pass UIControlEventValueChanged to the forControlEvents parameter of this method.

Here—I want to demonstrate this to you. In this example, we will have a table view controller that displays the date and time formatted as strings. Once the user refreshes the list by pulling it down, we will add the current date and time again to the list and refresh our table view. This way, every time the user pulls the list down, it triggers a refresh that will allow us to add the current date and time to the list and refresh the table view to display the new date and time. So let’s start in the implementation file of our table view controller and define our refresh control and our data source:

#import "ViewController.h"

static NSString *CellIdentifier = @"Cell";

@interface ViewController ()
@property (nonatomic, strong) NSMutableArray *allTimes;
@property (nonatomic, strong) UIRefreshControl *refreshControl;

@implementation ViewController

The allTimes property is a simple mutable array that will contain all the instances of NSDate in it as the user refreshes the table view. We have already seen the initialization of our table view controller in the Solution section of this recipe, so I won’t write it again here. But as you saw there, we have hooked the UIControlEventValueChanged event of our refresh control to a method called handleRefresh:. In this method, all we are going to do is add the current date and time to our array of dates and times and then refresh the table view:

- (void) handleRefresh:(id)paramSender{

    /* Put a bit of delay between when the refresh control is released
     and when we actually do the refreshing to make the UI look a bit
     smoother than just doing the update without the animation */
    int64_t delayInSeconds = 1.0f;
    dispatch_time_t popTime =
        dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);

    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){

        /* Add the current date to the list of dates that we have
         so that when the table view is refreshed, a new item will appear
         on the screen so that the user will see the difference between
         the before and the after of the refresh */
        [self.allTimes addObject:[NSDate date]];

        [self.refreshControl endRefreshing];

        NSIndexPath *indexPathOfNewRow =
            [NSIndexPath indexPathForRow:self.allTimes.count-1 inSection:0];



Last but not least, we will provide the date to our table view through the table view’s delegate and data source methods:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return 1;

- (NSInteger)tableView:(UITableView *)tableView
    return self.allTimes.count;

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath{

    UITableViewCell *cell = [tableView

    cell.textLabel.text = [NSString stringWithFormat:@"%@",

    return cell;

Give this a go in either the simulator or the device. Once you open the app, at first you will see only one date/time added to the list. Keep dragging the table view down to get more items in the list (see Figure 4-24).

See Also

Recipe 4.9

Get iOS 7 Programming Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.