Back in 2011, I wanted to implement Pull to refresh in one of my apps. The problem I encountered was that because iOS 5 had only been out for a short time, the standard PullToRefresh libraries (most notably EGOTableViewPullRefresh) hadn't been updated for iOS 5 or ARC. Converting the code to ARC is easy enough with Xcode's Refactor tool but I was also looking to use the code on a UIWebView and there was no documentation for how to set that up.
Luckily, I came across a fork of the EgoPullToRefresh code at GitHub called PullToRefreshView by iStopped, which had a very good README file with directions on how to implement for both a UITableView and a UIWebView. Also, there was a lot less code that needed to go into your controller as compared to the original EGOTableViewPullRefresh code. I built upon this code base.
Let's get started
I created my own fork of PullToRefreshView, which is available here. So, if you haven't already gotten it, go get it. Add PullToRefreshView.h, PullToRefreshView.m arrow.png and firstname.lastname@example.org to your project, you'll also need to add the QuartzCore framework and the AudioToolbox framework. Once you've done that, you can start adding code to your project.
For a UITableView, it's really simple. First, #import "PullToRefreshView.h" in your viewcontroller's .h file:
Now add an iVar to your viewcontroller's .m file:
Then add the following to your UITableViewController in ViewDidLoad:
Next, you simply add the delegate method for when the user pulls to refresh:
Finally, in your reloadTableData method, call finish
A couple of Tricks
One of the first things I noticed was that my app would freeze while it was loading data. This really annoyed me, probably because I've gotten so used to other apps like Facebook or Twitter that still allow you to scroll up and down while the app is reloading it's data after pulling to refresh. To fix that we change our delegate to look like so.
Pretty self explanatory, this basically runs the task in the background.
The second thing I noticed was that there wasn't a way for me to trigger the Pull to Refresh code without, well, pulling to refresh... I wanted to be able to trigger it when bringing the app back to the foreground. Here's how we do that.
Add the following code to ViewDidLoad
Then add this to your UITableView:
The first line scrolls the view so you can see the loading "screen", the second line sets the state of your pull scrollView to loading and the third is your call to reload your table data. Now your PullToRefreshView will fire when you bring the app back into the foreground.
PullToRefresh a UIWebView
Working with a UIWebView is slightly more complicated because there's a few more steps involved. In the controller that contains your UIWebView, create an iVar for your scrollView:
Next, in ViewDidLoad make the UIWebView a delegate to itself and give it a tag:
Now add the following to your ViewDidLoad:
Now you can set up your PullToRefreshView scrollView and add it to the webView:
You'll probably get a warning on line 3 ([pull setDelegate:self]), if so, go into the .h file of your controller and #import PullToRefreshView.h then add <PullToRefreshViewDelegate> to your @interface declaration like so:
That should squash the warning. Or you could skip all that and typedef the setDelegate method like so: ([pull setDelegate:(id)self]), the choice is yours. Moving right along, add the following to your controller:
Then in your webViewDidFinishLoad method, add the following:
That's it. Now you have Pull To Refresh working in your UIWebView. Thanks to iStopped for his work on this. If this blog post helped you, please consider following me on Twitter.