Refresh Control Changes in iOS 10

Apple first added the pull-to-refresh style user interface control way back in iOS 6. Unfortunately it only worked with a table view controller. You were out of luck if you wanted to use it with a plain scroll view or collection views. After a long wait Apple enthusiastically announced at WWDC 2016 that iOS 10 was bringing refresh controls to the scroll view and by inheritance to table and collection views. This post walks you through what you need to know.

Refresh Control

New in iOS 10

Starting with iOS 10 a UIScrollView has a refreshControl property that you can set to a UIRefreshControl. As always you do not need to manage the frame of the control. Just configure the control, set the target-action for the valueChanged event and assign to the property.

Even better, both a UITableView and UICollectionView inherit from UIScrollView so they also get the refreshControl property. This means you can easily add a refresh control to scroll views, table views (without needing a table view controller) and collection views.

As I write this there is no support in Interface Builder (Xcode 8.1) for this new refreshControl property. If you want to add a refresh control to a scroll, table or collection view you must do it in code. You can still use Interface Builder to add a refresh control to a table view controller. For full details of the pre-iOS 10 approach see this earlier post

A Scroll View Example

I am going to reuse a scroll view project from an earlier post as an example. My fake sign up screen has two labels and buttons in a vertical stack view. To make sure the view is always visible even when there is an unexpected keyboard onscreen the stack view is inside a scroll view:

A Stack View in a Scroll View

Now suppose I want to allow my user to refresh the sign up screen (maybe to check for extra choices). Let’s look at the simple steps to add a refresh control to this scroll view.

Creating a Refresh Control

Regardless of whether you are using a plain scroll view, table view or collection view the steps to create a refresh control are the same. For this example I added the following code to the viewDidLoad method of the view controller (scrollView is an IBOutlet property connected to the UIScrollView in Interface Builder):

if #available(iOS 10.0, *) {
  let refreshControl = UIRefreshControl()
  let title = NSLocalizedString("PullToRefresh", comment: "Pull to refresh")
  refreshControl.attributedTitle = NSAttributedString(string: title)
  refreshControl.addTarget(self,
                           action: #selector(refreshOptions(sender:)),
                           for: .valueChanged)
  scrollView.refreshControl = refreshControl
}

Notes:

  • The refreshControl property of UIScrollView is only available in iOS 10 so we first test for availability.

  • You can use the plain initializer UIRefreshControl() to create a new refresh control. You do not need to set the frame, UIKit manages it for you when you add the control to the scroll view.

  • The attributedTitle is not needed but allows you to set a text message to display below the spinner when the control is refreshing. Note that it is an NSAttributedString. Also remember to localize the title if you use one.

  • The action method is for the valueChanged event.

The action method takes the refresh control as the sender, does whatever it needs to refresh the content and then calls endRefreshing to hide the refresh control. For example:

@objc private func refreshOptions(sender: UIRefreshControl) {
  // Perform actions to refresh the content
  // ...
  // and then dismiss the control
  sender.endRefreshing()
}

Note you need the objc as I made the function private and by default a private Swift method is not visible to the Objective-C runtime.

In the sample code I toggle the visibility of the orange choice each time but the details are not important. The appearance when we pull down on the scroll view:

Refreshing a Scroll View

That’s all there is to it!

Sample Code

The code is simple but if you want to see the full example project you can find it in my GitHub repository at RefreshScroll.

Further Reading

See the wonderfully enthusiastic announcement from WWDC 2016 that refresh controls were coming to scroll views, collection views and table views:

For a walk through of the old way using Interface Builder to add a refresh control to a table view controller see this post from 2013 (updated for Xcode 8):