651.288.7000 info@intertech.com

We’ve all seen them in apps: a screen is refreshed by pulling down on the view. 


A little wheel starts spinning at the top, until the refresh has completed.  At that time, the wheel disappears, and the view bounces back into place.  Many of us have built our own custom versions of this functionality, however, as of iOS 6, things have gotten quite a bit easier. 

Introducing the UIRefreshControl, which is now a part of CocoaTouch in the iOS 6 SDK.  In order to use this with a Table View (right now, this control is only available for tables) follow these steps:

  1. Create a callback method to handle your refresh logic.
  2. Instantiate the UIRefreshControl with a basic “alloc/init”
  3. Connect an action to the refresh control to invoke your callback method when the ValueChange event is fired.
  4. Add the refresh control to the Table View Controller’s “refreshControl” property.


Step 1:

Create the “callback” method that in invoked when a user pulls down on the Table View.  The signature of the method should take one parameter: a pointer to the UIRefreshControl.  This control object has a couple of methods available to show (beginRefreshing) and hide (endRefreshing) itself.   Since this callback method won’t be invoked until the control has already started running, there is no need to call beginRefreshing here.

   1: -(void)refreshView:(UIRefreshControl *)refresh {
   2:     refresh.attributedTitle = [[NSAttributedString alloc] initWithString:@"Refreshing data..."];
   4:     // custom refresh logic would be placed here...
   6:     NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
   7:     [formatter setDateFormat:@"MMM d, h:mm a"];
   8:     NSString *lastUpdated = [NSString stringWithFormat:@"Last updated on %@", 
   9:                                    [formatter stringFromDate:[NSDate date]]];
  10:     refresh.attributedTitle = [[NSAttributedString alloc] initWithString:lastUpdated];
  11:     [refresh endRefreshing];
  12: }

Line 2 changes the text below the refresh icon to  “Refreshing data…”   You’ll notice that you can’t simply use a basic NSString with this control.  Instead, you’ll create an NSAttributedString (a String that allows you to define characteristics, such as a font, for a range of its characters).   After that, your custom refresh logic is executed (such as hitting a RESTful web service for the latest data).

Lines 6 – 10 are executed after the data has been refreshed.  In this case, an informational message is displayed below the refresh icon that reminds the user when the last update occurred.

Line 11 stops and hides the spinning refresh icon, and automatically pulls the Table View back into place.


Steps 2 – 4:

   1: // Inside a Table View Controller's viewDidLoad method
   2: UIRefreshControl *refresh = [[UIRefreshControl alloc] init];
   3: refresh.attributedTitle = [[NSAttributedString alloc] initWithString:@"Pull to Refresh"];
   4: [refresh addTarget:self
   5:          action:@selector(refreshView:)
   6:          forControlEvents:UIControlEventValueChanged];
   7: self.refreshControl = refresh;

Line 2 is self explanatory… since UIRefreshControl is part of UIKit in CocoaTouch, you’ll already have the necessary framework imported.

On line 3, you’ll set the initial message to the instructional “Pull to Refresh.”

Lines 4 – 6 show how to link your callback method to the “Value Change” event (which occurs when the user pulls down on the table view).  Most people are used to hooking up IBActions for controls… this is the programmatic way to do it.

Finally, line 7 assigns the UIRefeshControl to the Table View Controller’s “refreshControl” property (note that this is assigned to the View Controller, not the Table View).


Running the Code:

The initial view shows your table…


When the user pulls down on the table, they see the refresh control with the initial instructional message…


As the user continues to pull the table down, the icon begins to stretch…


Once they pull down far enough, the table view snaps back a bit, the refresh icon changes to a spinning gear, and the active “Refreshing data…” message is displayed…


Finally, once it’s finished, the refresh control disappears and the table snaps back into place.  The next time the user pulls down on the table, they’ll see an informational “Last updated on” message…



Interface Builder:

You may be wondering, “isn’t there a way to do this in InterfaceBuilder?”  The answer is: yes, in part.  You won’t find the control in the Object Library.  However, you can add the refresh by selecting the Table View Controller and configuring it in the Attributes Inspector.  Setting the “Refreshing” option to “Enabled,” takes care of instantiating the UIRefreshControl with an attributed title, and assigns it to the Table View Controller’s “refreshControl” property.  So if you want to access the control programmatically, you do not need to create an IBOutlet… just use that property.


You won’t see any visual indication in the Table View Controller’s scene that it has been added, however if you look at the View Controller Hierarchy, it does list a “Refresh Control.”


Now, you would naturally assume that you can do a secondary click on this Refresh Control and drag from the Value Changed event to your View Controller’s header file (thus auto-generating an IBAction skeleton)…  and while it appears you can…


…the action never fires.  Instead of creating an IBAction, you’ll need to programmatically assign the action to your callback method.   Use the refreshControl property for this purpose:

   1: // Inside a Table View Controller's viewDidLoad method
   2: [self.refreshControl addTarget:self
   3:                      action:@selector(refreshView:)
   4:                      forControlEvents:UIControlEventValueChanged];

iOS 6 as a GA release is only a few weeks old, so perhaps we’ll see this fixed and/or a visual control added to the Object Library in Interface Builder soon!

Like What You've Read?

Subscribe to the Blog.

Every Friday we send that week's content from our Developers via email. Try it out!

Some ad blockers can block the form below.

You have Successfully Subscribed!

Pin It on Pinterest

Share This