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. Examples of a refresh control in two of its different states are shown in Figure 4-25.
Simply create a table view controller (as discussed in Recipe 4.13)
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
)
{
/* Create the refresh control */
self
.
refreshControl
=
[[
UIRefreshControl
alloc
]
init
];
self
.
refreshControl
=
self
.
refreshControl
;
[
self
.
refreshControl
addTarget:
self
action:
@selector
(
handleRefresh:
)
forControlEvents:
UIControlEventValueChanged
];
}
return
self
;
}
Refresh controls are a new UI component added to the iOS 6
SDK. They 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 iOS 6, 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 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 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"
@interface
ViewController
()
@property
(
nonatomic
,
strong
)
NSMutableArray
*
times
;
@property
(
nonatomic
,
strong
)
UIRefreshControl
*
refreshControl
;
@end
@implementation
ViewController
...
The times
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 date 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
.
times
addObject:
[
NSDate
date
]];
[
self
.
refreshControl
endRefreshing
];
[
self
.
tableView
reloadData
];
});
}
Last but not least, we will provide the date to our table view through the table view’s delegate and data source methods:
-
(
id
)
initWithStyle:
(
UITableViewStyle
)
style
{
self
=
[
super
initWithStyle:
style
];
if
(
self
)
{
self
.
times
=
[
NSMutableArray
arrayWithObject:
[
NSDate
date
]];
/* Create the refresh control */
self
.
refreshControl
=
[[
UIRefreshControl
alloc
]
init
];
self
.
refreshControl
=
self
.
refreshControl
;
[
self
.
refreshControl
addTarget:
self
action:
@selector
(
handleRefresh:
)
forControlEvents:
UIControlEventValueChanged
];
}
return
self
;
}
-
(
NSInteger
)
numberOfSectionsInTableView:
(
UITableView
*
)
tableView
{
return
1
;
}
-
(
NSInteger
)
tableView:
(
UITableView
*
)
tableView
numberOfRowsInSection:
(
NSInteger
)
section
{
return
self
.
times
.
count
;
}
-
(
UITableViewCell
*
)
tableView:
(
UITableView
*
)
tableView
cellForRowAtIndexPath:
(
NSIndexPath
*
)
indexPath
{
static
NSString
*
CellIdentifier
=
@"Cell"
;
UITableViewCell
*
cell
=
[
tableView
dequeueReusableCellWithIdentifier:
CellIdentifier
];
if
(
cell
==
nil
)
{
cell
=
[[
UITableViewCell
alloc
]
initWithStyle:
UITableViewCellStyleDefault
reuseIdentifier:
CellIdentifier
];
}
cell
.
textLabel
.
text
=
[
NSString
stringWithFormat:
@"%@"
,
self
.
times
[
indexPath
.
row
]];
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-26).
Get iOS 6 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.