Show Menu

Need an iOS Developer?

Submit your 30 day Job Listing for FREE

If you love your iOS Application and like to make sure that branding is consistent throughout then it might be a good idea to customise the Pull to Refresh feature.

There is some debate whether or not the iOS Custom Pull to Fresh feature is useful or even if it should exist at all. Some people get really passionate about it. Enough to write quotes and an entire article condemning it:

“A RELIC OF A BYGONE ERA”
Austin Car : Why The Pull-To-Refresh Gesture Must Die

Within the iOS SDK, UIKit gives us UIRefreshControl. UIRefreshControl can be used to quickly add the Pull to Refresh option within a UITableView.

UIRefreshControl also comes with a very simple interface and it can be easily integrated into a UIScrollView. This option however does not leave much room for customisation.

The best way to go about creating a pull to refresh is to actually forget about the UIRefreshControl. WHAT? Yes, you heard correct. The way to start is to use a UIControl subclass. When you subclass UIControl instead of the UIView you get access to all the actions and touch handling methods that are associated with [externallink url=”https://developer.apple.com/library/ios/documentation/uikit/reference/uicontrol_class/reference/reference.html” text=”UIControl”]. So, this now makes building the custom pull to refresh the same as if you were building any other iOS view.

Getting the custom pull to refresh to interact correctly with a UIScrollView (or any subclass of UIScrollView like the UITableView / UICollectionView) is a little harder to do.

Position the Pull to Refresh

If you’ve ever seen a custom pull to refresh then you know that the position is important. You want it so that it is scrolled up and off the top of the iOS View. That is the basic animation. To make it a little nicer we’ll make it so that the UIScrollView bounces back to the default position when it is scrolled beyond the top of its content. This custom pull to refresh effect off the top of the screen will imitate the UIRefreshControl behaviour. So achieve this effect the custom pull to refresh will will need to be added as a subview of UIScrollView (or subclass thereof) and then have its y coordinate set to the negative of its height:


- (void)viewDidLoad
{
    [super viewDidLoad];
 
    CGFloat customRefreshControlHeight = 50.0f;
    CGFloat customRefreshControlWidth = 320.0f;
    CGRect customRefreshControlFrame = CGRectMake(0.0f,
                                                  -customRefreshControlHeight,
                                                  customRefreshControlWidth,
                                                  customRefreshControlHeight);
 
    self.customRefreshControl = [[CustomRefreshControl alloc] initWithFrame:customRefreshControlFrame];
 
    [self.tableView addSubview:self.customRefreshControl];
}

Fire the Pull to Refresh

We now need fire an action for our custom pull to refresh when the scroll view, that contains the custom pull ro refresh has scrolled far enough and also when the user dragging has ended. This means that the custom pull to refresh needs to know a few things:

  • How far it has been scrolled
  • When the scroll view’s end-dragging event has occurred

There are, like most things a few ways to achieve this. One, not so flexible way is to set the iOS view delegate for the custom pull to refresh and make sure you have implemented the UIScrollViewDelegate methods within said custom pull to refresh class. This does have a draw back i’m afraid. It now means that your view controller will no longer be able to be used as the scroll view delegate.

The second, and more flexible way is to add a method to your custom pull-to-refresh that informs it of the two things listed above. This method can then be called from wherever the scroll view’s delegate implements the [UIScrollViewDelegate scrollViewDidEndDragging:willDecelerate:] method.


- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    [self.customRefreshControl containingScrollViewDidEndDragging:scrollView];
}  

Within the implementation of containingScrollViewDidEndDragging:, you can then check the scroll view’s content offset and fire an action when appropriate.


- (void)containingScrollViewDidEndDragging:(UIScrollView *)containingScrollView
{
    CGFloat minOffsetToTriggerRefresh = 50.0f;
    if (containingScrollView.contentOffset.y <= -minOffsetToTriggerRefresh) {
        [self sendActionsForControlEvents:UIControlEventValueChanged];
    }
}

Note: After initialling your iOS custom pull to refresh, if you want your action to be able to correctly call a selector then the target and delector must be set.


[self.customRefreshControl addTarget:self
                              action:@selector(refresh)
                    forControlEvents:UIControlEventValueChanged];

That's it! You should now have a fully functional and beautiful iOS Custom Pull to Refresh. Pretty neat right. Well, there is even more things that can be done.

Room for Improvement?

You may want your custom pull-to-refresh feature to stay open while the device is waiting for new data to load or have an animation that is based on the content offset of the containing scroll view. Sounds interesting right? Well there is a simple solution that will allow you to include these easily. You can add the containingScrollViewDidScroll: method. This works a little like the containingScrollViewDidEndDragging: I mentioned earlier. When you call containingScrollViewDidScroll: from the implementation of [UIScrollViewDelegate scrollViewDidScroll:] it allows the custom pull-to-refresh important stuff, like:

  • It can keep track of whether or not it has scrolled into view
  • When it is scrolling
  • How much it has scrolled

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    [self.customRefreshControl containingScrollViewDidScroll:scrollView];
}

Pre-Built Solutions

Now, This is what I love about the iOS Application Development community. The flush amount of pre-built libraries and code out there for people to use. Just because the person who created them was passionate enough. That is really something, isn't it?

SpiralPullToRefresh for iOS - Twitter Music-like pull-to-refresh controller but a bit more enhanced and flexible. Additionally, it supports 3 types of waiting animations: random flashing, linear flashing and circular flashing. Moreover particles gathering together using a galaxy/spiral animation.

BOZPongRefreshControl
custom pull to refresh iOS

This is an awesome pull-down-to-refresh control for iOS that plays pong.

If there are any that you like and/or use then please comment with a url below and I will add them

having issues?

We have a Questions and Answer section where you can ask your iOS Development questions to thousands of iOS Developers.

Ask Question

FREE Download!

Get your FREE Swift 2 Cheat Sheet and quick reference guide PDF download when you sign up to SwiftMonthly


Sharing is caring

If you enjoyed this tutorial, please help us and others by sharing using one of the social media buttons below.


Written by:

I work in the shadows. You can thank me by being a good soul.

Comments

comments