Code for You iOS Portfolio
PullToRefresh iOS 5 and ARC Tutorial
December 14, 2011
123
, , , ,

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 arrow@2x.png 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

Your done.

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.

About author

Sonny Parlin

Jiu Jitsu practitioner training under Rob Kahn at Gracie Tampa, medical marijuana activist, musician, hacker, and libertarian.

Related items

/ You may check this items as well

Screen Shot 2013-11-14 at 1.49.45 AM

Facebook Messenger for iOS Updated with New design and “Free Texting”

Back in 2011, I wanted to implement Pull to refres...

Read more
jjlog

The technology behind Jiu Jitsu Log 2.0

Back in 2011, I wanted to implement Pull to refres...

Read more
Screen Shot 2013-11-13 at 1.54.36 PM

Top-down interface orientations in a UITabBarController app

Back in 2011, I wanted to implement Pull to refres...

Read more
  • http://www.margin.se Mattias H

    When I refactor PullToRefreshView I get two errors.
    XCode complains about this line:
    @property (nonatomic, assign) id delegate;

    PullToRefreshView.m:42:13: error: existing ivar ‘delegate’ for property ‘delegate’ with assign attribute must be __unsafe_unretained [5]
    @synthesize delegate, scrollView;

    PullToRefreshView/PullToRefreshView.h:52:61: note: property declared here [2]
    @property (nonatomic, assign) id delegate;

    Do you have any idea why this is happening to me?

  • Sonny Parlin

    Change the property in PullToRefreshView.h to this:

    @property (nonatomic, strong) id<PullToRefreshViewDelegate> delegate;

    So change it from “assign” to “strong”.

    • http://iphone.galloway.me.uk/ Matt Galloway

      Woah, no, do *not* do that. That will very very likely introduce a retain circle. You need to add “__unsafe_unretained” to the ivar declaration.

      • Sonny Parlin

        Yes, thanks. My response to his comment was before I did research on ARC and delegates. I’ve since changed my code to NOT use an ivar and my delegate property now looks like this:

        @property (nonatomic, weak) id<PullToRefreshViewDelegate> delegate;

        With “weak” being the same as unsafe_unretained. After playing around with the code, I just commented out the iVar’s. I’m not sure why, but the author had ivars with identical names to the properties that were declared. I played with commenting them out and all was (and has been) fine since.

        • Jason

          When popping the view with the refresh in it (back up the navigation hierarchy), I had the run-time problem:

          An instance 0x813d540 of class _UIWebViewScrollView was deallocated while key value observers were still registered with it. Observation info was leaked, and may even become mistakenly attached to some other object. Set a breakpoint on NSKVODeallocateBreak to stop here in the debugger. Here’s the current observation info:
          (
          <NSKeyValueObservance 0x800b180: Observer: 0x8011f70, Key path: contentOffset, Options: Context: 0x0, Property: 0x800b070>

          It seems to be that the scrollView is going away because it is weak. Not really knowing what’s up, I found that it works when you change the UIScrollview property to strong. Foolish?

          • Sonny Parlin

            Instead of changing the property, you should add a dealloc method to the controller with the pullToRefresh code and remove your observer. For example:

            – (void)dealloc {
            [[NSNotificationCenter defaultCenter] removeObserver:self];
            [super dealloc];
            }

          • Anthony

            I’ve run into a similar problem and I tried the solution presented below. It resolves the crash but I still get the following runtime message in my log:

            An instance 0x8b13000 of class BaseTableView was deallocated while key value observers were still registered with it. Observation info was leaked, and may even become mistakenly attached to some other object. Set a breakpoint on NSKVODeallocateBreak to stop here in the debugger. Here’s the current observation info:
            (
            <NSKeyValueObservance 0x8249920: Observer: 0x82cf3c0, Key path: contentOffset, Options: Context: 0x0, Property: 0x82d0df0>
            )

            I added this to my controller

            – (void)dealloc {
            // To fix the weird PullToRefresh crash, still complains about a leak thoughh?
            [[NSNotificationCenter defaultCenter] removeObserver:self];
            }

            Note that you can’t call [super dealloc] in ARC code.

            Any ideas?

          • Marcel Wlotzka

            This is what I added to my wievController:

            – (void)dealloc {
            [pull removeFromSuperview];
            }

            Of cause you need to create an iVar for pull with this code, but then it works for me without crashes or warnings!

  • http://www.margin.se Mattias H

    What do you know! It works! Thank you! I do have a clear memory that I did that earlier… but there are a few classes in my project now and I might have been somewhere else… was kind of exhausted yesterday.

    Once again Thank you!

  • Sonny Parlin

    No problem, glad you got it working!

  • Pingback: iOS: Pull To Refresh error()

  • Ricky

    Thanks for this code! It’s been a real help and has been working well. One issue I’ve run into is that if I have a webView where I can scroll laterally, it scrolls the PTR view laterally as well. Have you seen this behavior before?

    • Sonny Parlin

      I haven’t seen that, but that’s probably because I’ve never set up a webView to scroll horizontally… Sorry.

      • Ricky

        Thanks for the reply. I didn’t set up the webView to scroll horizontally intentionally. I just loaded a website that was wider than the width of the webView (such as the desktop version of Google on iPad or iPhone), and I saw that behavior.

  • http://www.GladiatorApps.com John Mattos

    This is 100% badass. Thanks so much for your effort, and for taking the time to write it up so clearly. I’m definitely going to follow your lead. Great job!

  • Ken

    Could you post a very basic demo app of both the table and webview in action? I can’t seem to get this working and it would be easier if I could see the basics and integrate it into my existing app. Thanks so much!

  • Sonny

    Ken, I don’t have time these days to create one but maybe I could help you gt yours working. Can you be more specific with what your issue is?

  • Ken

    Thanks, Sonny, I was able to figure it out. The problem was that the Quartz framework was not linked in my application, so converting iStop’s class kept throwing errors. After linking the framework everything worked just fine. Thanks for posting this tutorial. Very useful!

  • Damon Aw

    This is a very good tutorial. Thank you so much!

    I met into some warnings when I tried to do ARC refactor. It says [blah blah release] is forbidden in ARC.

    I got PullToRefresh to work by deleting all the [xyz release] line. Is it okay to do so?

    • Sonny Parlin

      Yes, with Automatic Reference Counting (ARC) all memory management is handled for you, so no need to release, retain, etc…

      • Damon Aw

        Thanks man!

        I saw a thread on Stackoverflow on not needing release, retain, dealloc too, *gulp* its a little bit uncomfortable for a noob to be deleting lines from an external library. =)

  • johnyeong

    Hi Sonny,
    I’m currently facing a problem here. When the code sets the pull object state-
    [pull setState:PullToRefreshViewStateLoading];

    The state, indicator and so forth works fine. However, it just stops there and does not move on to the next line of code in the function(Just continues to be in loading state). I presume it did not move to the next line to call my reloadTableData function-

    -(void)reloadTableData
    {
    [self.tableView reloadData];
    [pull finishedLoading];
    }

    After:-
    [pull setState:PullToRefreshViewStateLoading];

    This didnt load:
    [self performSelectorInBackground:@selector(reloadTableData) withObject:nil];

    Please help. Thxxx.

  • Sonny

    Does it crash or just hang?

    • johnyeong

      It didnt crash. The activity indicator just continued to spin. It doesnt refresh the view, but i can still continue to navigate through the application like normal.

      • Sonny Parlin

        Are you sure -finishedLoading is being called?

  • johnyeong

    Hi Sonny,
    To be exact, this is what i meant(I am actually trying to refresh an RSS feed):

    -(void)pullToRefreshViewShouldRefresh:(PullToRefreshView*)view
    {
    [self performSelectorInBackground:@selector(reloadTableData) withObject:nil];
    }

    -(void)reloadTableData
    {
    _rssParser = [[RSSParser alloc] initWithRSSURL:tempWebString];
    [_rssParser setDelegate:self];
    [_rssParser start];
    [readerTable performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES];
    [pull finishedLoading];
    }

    The application hangs when i try to refresh the view.

    However, when i changed it to:

    -(void)pullToRefreshViewShouldRefresh:(PullToRefreshView*)view
    {
    [self reloadTableData];
    }
    This works. However, i still cannot run it on the background, which i am still looking for that solution awhile here now.

    Thxx,

    • Sonny Parlin

      Is it possible that you could add

      [pull finishedLoading];

      to your reloadData method and remove it from reloadTableData?? I would experiment with stuff like that…

      • johnyeong

        err, the reloadData selector is actually a reserved function to call reloadData in the table. Therefore after switching the function back to [self.tableView reloadData] it actually brings the same result, only cleaner.

  • Sonny Parlin

    Without playing with your code, my guess is that it would have something to do with the way you’re calling your reloadData method, in other words, I think that

    performSelectorInBackground and performSelectorOnMainThread might be mutually exclusive. You initially tell the app to perform something in the background, then you tell it to perform it on the main thread. This might be the cause of it hanging (just a guess). You may want to try and find a different way to call reloadData, maybe using a delegate or a notification.

    • johnyeong

      Hihi, thanks alot. I guess you were right. performSelectorOnMainThread had a bad effect on the performSelectorOnBackground function. The problem still persisted however. Found out that i cannot alloc another object while the job is processing in the background.

      I have one more question though… The loading is running abit too fast, so fast that nobody actually believes that my feeds are being refreshed. Is there is proper way to delay the loading time?(Like just let the user see that i am loading)

      Thxx

      • Sonny Parlin

        That seems odd to me, did you replace the performSelectorOnMainThread with a call to performSelectorOnBackground inside your -(void)reloadTableData method? If so, that’s not going to give you an accurate loading time. You should replace your call performSelectorOnMainThread method call to reload the data in your table to use a delegate. Of course, I’m guessing here.

        • johnyeong

          err, no. I mean, the loading time was still different. What i meant was too fast. Anyway, solved the problem(The main point of this implementation was to ensure users know something is loading, because they do not see the table being refreshed).This was my way:

          sleep(unsigned int);

  • Aaron

    Thank you! Excellent, clear writeup.

  • http://franklinwebber.com Franklin Webber

    I’m confused why your fork is not an actual fork of the original project.

    • Sonny Parlin

      That’s a great question… A few reasons (none of them are probably good):

      1. I made a bunch of changes to the code before I decided to throw it up on GitHub for public consumption.
      2. I wasn’t sure who’s project to fork because there were multiple sources including iStopped, chpwn, and enormego.
      3. I figured it was widely documented as to where the sources came from so it didn’t really matter (as you can see from the original copyrights in the sources I uploaded to GitHub ).

  • Peter

    Hi Sonny, Thanks for the code! Works great in my application but I noticed a problem if I pull/swipe down too far it can crash my app. Have you noticed this behavior? I wonder if a “contentOffset.y” max could be set to limit down scroll. Thanks in advance.

    • Sonny Parlin

      If that’s happening, there’s likely a deeper problem and setting a limit on how far you scroll would only be hiding the problem, not solving it.

    • Sonny Parlin

      Have you tried setting a breakpoint?

      • Peter

        I just noticed this feature :) while testing on my device. Debugging will be my next step! Thanks for the prompt response.

  • Ryan

    Dude!!!! Awesome!!! Thank you so much!!!!!!!!

  • Ryan C

    Works great except when I have a navigation controller. On the first view of the nav controller I have a uitableview and I add an instance of PullToRefreshView. Now I push another view/viewcontroller that also has a uitableview and an instance of PullToRefreshView. Everything still works fine, as expected. Now when I go to pop the nav controller back to the first I receive the error message below. Also the PullToRefreshView stops working properly. Any ideas???

    An instance 0xdc4d000 of class UITableView was deallocated while key value observers were still registered with it. Observation info was leaked, and may even become mistakenly attached to some other object. Set a breakpoint on NSKVODeallocateBreak to stop here in the debugger. Here’s the current observation info:
    (
    <NSKeyValueObservance 0x192e90: Observer: 0x1cc560, Key path: contentOffset, Options: Context: 0x0, Property: 0x1b87c0>

    • Sonny Parlin

      You should add a dealloc method and remove your observer. For example:

      – (void)dealloc {
      [[NSNotificationCenter defaultCenter] removeObserver:self];
      [super dealloc];
      }

      Do this in the view getting popped. I’ve read that it’s good practice to remove any observers you create in a dealloc method.

  • Evan Roth

    Hi- wanted to thank you for posting this, I’ve been working on implementing it and am running into a problem. When I trigger the pull-to-refresh action, there’s no spinner visible in the PTR view and it executes very quickly. The minute one pulls the scrollview down far enough to trigger the PTR and lets go, it snaps back up immediately. It does still execute the refresh method, though, which involves reinitiating an asynchronous NSURL connection- just wondering how I can get this to implement. Any help would be greatly appreciated!

    Thanks,
    Evan

    • Evan Roth

      Let me be a little more specific- PTR View looks like it’s not hitting the PullToRefreshViewStateLoading method for some reason, which seems to handle the “Loading” state, and the spinner triggering.

    • Sonny Parlin

      Sorry, you will have to post some code… use pastebin (http://pastebin.com/) and then provide a link to your paste.

      • Evan Roth

        Just thought of something after rereading the instructions- I wasn’t able to refactor the project I’m working on to ARC, as I received an error I wasn’t able to resolve:

        if (self = [super init]) (“Cannot assign to ‘self’ outside of a method in the init family”

        Will I still be able to implement pull to refresh if I’m not using ARC?

      • Evan Roth

        Sonny,

        Here’s a link to the parts of the code that call and use PTR. Please let me know if you need me to include anything else.

        http://pastebin.com/JU0cWeKX

        Thanks in advance for any help!
        Evan

        • Sonny Parlin

          You have to remove all references to retain and release from your code.

  • http://www.leaguegaming.com Tristan

    This code looks great,

    However I can not get a working example with the latest version of xcode, Tried to go through the comments as the example has changed based on feedback(?).

    Can anyone post an example project? It would be greatly appreciated :)

    • http://www.leaguegaming.com Tristan

      Oh, forgot to mention,

      Trying to do a simple UIWebView that refreshes when pulled down. Any project code done that has this would help so much!

    • http://www.leaguegaming.com Tristan

      hehe nevermind

      After doing a google search on my error, got it to work!

      Awesome man, Great help!

  • Sonny Parlin

    @Anthony, try doing this:

    – (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self forKeyPath:@”contentOffset”];
    }

    • Jarod

      I tried this to attempt to get rid of the observer warning message but not it crashes with this.

      *** Terminating app due to uncaught exception ‘NSRangeException’, reason: ‘Cannot remove an observer for the key path “contentOffset” from because it is not registered as an observer.’
      *** First throw call stack:
      (0x1c2a022 0x2013cd6 0x1bd2a48 0x1bd29b9 0x1583c84 0x1583901 0xf59c 0x2026e3d 0xd3bcbe 0xee30be 0xee33c7 0xee3436 0xc93e49 0xc93f34 0x57fb54 0x2287509 0x1b61803 0x1b60d84 0x1b60c9b 0x24167d8 0x241688a 0xc63626 0x24dd 0x2445)
      terminate called throwing an exception(lldb)

      • Jarod

        Fixed it by using this

        Fixed it by adding the following dealloc method

        – (void)dealloc
        {
        [self.tableView removeObserver:pull forKeyPath:@”contentOffset”];
        }

  • Jarod

    I am planning no using this in an app that I will be publishing to the apple store. What do I need to do in terms of licensing?

    • Sonny Parlin

      Nothing at all, it’s open source.

      • Jarod

        Much appreciated!!! This works amazing and took 5 minutes to implement.

        • Sonny Parlin

          Glad I could help, I just took what I found out there, modified it a little and tutorialized it somewhat. :)

          • Jarod

            I do have one minor issue. The UITableView is being reloaded by making a call to a URL and getting a JSON response. I am using NSURLConnection which basically allows me to do a [connection start] method call and handle all of the data population and table creation in the connectionDidFinishLoading method. The refresh updates and starts that update again but the header goes away even though the table is still reloading. Does this need to be changed to a sync call so that the header maintains onscreen until the data is reloaded?

          • Jarod

            Never mind I got it working. I just changed where I call the [pull finishedLoading];

  • jeremiah

    Awesome tutorial and classes! I’m only having one issue. The arrow never shows up. I’ve added the files to my project and looked through the class to see whats going on but don’t see anything that should be stopping it. Any help?

    • Mike

      I am also missing the arrow graphic… everything else appears to work. Any ideas? :)

  • Giacomo

    Hi Sonny,
    Very good tutorial, thank you.
    I get an error during linkning phase:

    Undefined symbols for architecture i386:
    “_OBJC_CLASS_$_PullToRefreshView”, referenced from:
    objc-class-ref in MainViewController.o
    ld: symbol(s) not found for architecture i386
    clang: error: linker command failed with exit code 1 (use -v to see invocation)

    Any Idea?
    (thanks for help)

    • Giacomo

      I solved the problem by adding PullToRefreshView.m to the list of file to compile in the build phase.

  • http://geekmohican.com Erkin

    which code highlighter plugin are you using man?

  • http://pyraego.com Pyraego

    Getting these weird errors. Anyone have any ideas? Thanks in advanced!

    Undefined symbols for architecture armv7:
    “_OBJC_CLASS_$_CALayer”, referenced from:
    objc-class-ref in PullToRefreshView.o
    “_kCAGravityResizeAspect”, referenced from:
    -[PullToRefreshView initWithScrollView:] in PullToRefreshView.o
    “_CATransform3DMakeRotation”, referenced from:
    -[PullToRefreshView setImageFlipped:] in PullToRefreshView.o
    ld: symbol(s) not found for architecture armv7
    clang: error: linker command failed with exit code 1 (use -v to see invocation)

    • Sonny Parlin

      Looks like you need to link to the QuartzCore framework.

      • http://pyraego.com Pyraego

        excellent! that fixed the issue :)

        One more thing I am having an issue with. Got everything working great, except if you pull down really far on the pull to refresh, like past half screen and let go it blows up with an array out of bounds exception.

        “*** Terminating app due to uncaught exception ‘NSRangeException’, reason: ‘*** -[__NSArrayM objectAtIndex:]: index 5 beyond bounds for empty array'”

        This only occurs if you pull really far. Any ideas? Thanks again for all the help. Great plugin btw:)

        • http://pyraego.com Pyraego

          Figured out the issue! I was clearing my array when I did a reload. Thanks again for all the help! Excellent plugin!!

  • JZ Chen

    Hi ,
    the way you let the loading task to background
    – (void)pullToRefreshViewShouldRefresh:(PullToRefreshView *)view;
    {
    [self performSelectorInBackground:@selector(reloadTableData) withObject:nil];
    }
    the code above might potentially cause the apps crash.
    And I got the error message
    bool _WebTryThreadLock(bool), 0x8053ce0: Tried to obtain the web lock from a thread other than the main thread or the web thread. This may be a result of calling to UIKit from a secondary thread. Crashing now…
    I’m still trying out some other solutions to achieve the same goal.

    • SamiAlAwadhi

      Perhaps you should use performSelectorOnMainThread

  • Sonny

    You could always wait until you’re inside the thread you want to be in and then send to background…

    • JZ Chen

      and why can’t I work with UIViewController with a UITableView member inside the controller…
      Did I miss something with the code or…??
      Thanks for helping me out

  • Arnaud

    Hi all,

    I would like to use this PullToRefresh in a UITableView.

    This table view is a subView of a UIViewController.

    Is it ok with this script ?.

    Thanks a lot!

  • Denzyl

    Thanks for this. I’m running into one problem though: the activity spinner never gets activated. If I remove [pull finishedLoading] I can see it spin forever, but when every direction is followed, I just see the arrow up and then flip back down. I put a NSLog statement in the case for PullToRefreshViewStateLoading and it gets called but the animation just doesn’t happen (the flip happens right away with no visible activity indicator. Thanks for the any insight you might be able to provide.

    • tu0huang

      yeah same problem.
      It turns out you should put [pull finishedLoading] into callback of some http request; otherwise it immediately calls that method and no spinning indicator showing up

  • David

    That’s great, it works nice. Any pointers for me expanding the implementation to include being able to pull up from the bottom of a uitableview?
    Thanks,
    David

  • http://www.carlssonmedia.se Christopher

    Thanks for this, it works perfectly and a novice like myself can understand whats happening!

  • reno

    hey, I would to ask that the footer for pull to refresh doesn’t display the arrow direction properly when I drag till the end of the tableview and expand the cell in the table. Any advise. For the header, the arrow works fine. I really need some advise.

  • Cameron Farzaneh

    Hey I got a problem with Pull to Refresh on webview. So I created it and everything works perfectly however when I tap on the status bar, it does not scroll the webview on top. Does anyone know how to fix this?

  • Sonny Parlin

    Cameron,

    Send me your code and I’ll have a look… sonnyparlin@gmail.com.

  • johne

    I followed your steps, however I must scroll down first, then scroll up for the refresh-pulldown to appear (ie. the scroll bar must become visible). Any suggestions? I’d like the ability to refresh immediately after the Table loads.

  • John Doe

    Hello sonny.
    I am glad to use that.
    But when i scroll my webView to refresh my UIWebView in my iOS app, the first time and second time are okay and then third time and above time are not refresh anymore.
    Also ScrollView is not work.
    How can i do that brother?

  • Velibor

    Hello,
    I am glad to use it, as it is extremely easy to implement it. But there is a small problem. In my UITableView data are not refreshing after pulling and releasing. Interesting, there are not refreshing only for (I think) second half of data. By the way I have 20 rows in table, which is populated with data from net using TFHpple in conjuction with NSURLConnection.
    So, after getting data from net, first scroll to pull – there are no data below (except rows which are visible + 3-4 rows below them).
    If I scroll down to the end of table, and pull down after that, all is ok. I suppose the data are somehow cached.
    Thanks in advance on you reply, and sorry for my english.

  • http://www.forovietnam.com Foro Vietnam

    Thanks for sharing iOS5 because as you said, the Git version is quite old and not valid for ARC… you saved me lot of time.

  • Jessica Moore

    Hi Sonny, this is the best and easy to use tutorial for pull to refresh in iOS 5.

    Although its not working fine enough for me. When i pull it down, the little wheel keeps on spinning but it does not go away. No crashing or errors. I am using it only for tableview to parse a website. Can you suggest how to troubleshoot it.

    The app already has a splash screen and it appears that after the splash screen, it already shows the updated tableview cells.

    • Sonny Parlin

      Are you calling [pull finishedLoading]; after your data gets updated?

  • arslanjaved

     @sonnyjitsu Your library looks like a simplified version of EGOTableViewPullRefresh. I am able to use it with iOS 5 and it worked like a charm. I was wondering if you have some tutorial for EgoImageLoading for tableview in iOS 5?

    • http://e5media.com sonnyjitsu

       @arslanjaved Sorry, no… I don’t even know what EgoImageLoading is.

      • arslanjaved

         @sonnyjitsu  Its a library that helps you load image asynchronously from web and place it inside tableview. Like parsing a website. Can you suggest anything related to it? Thanks!

        • http://e5media.com sonnyjitsu

           @arslanjaved Here is a piece of code from one of my projects that does exactly that.
           
          https://gist.github.com/3650086

        • arslanjaved

           @sonnyjitsu GCD is something i haven’t learnt and its complicated. Anyways thanks for sharing it :) 

  • ChenCH1

    Hi Sonny, this is really a good reference for Pull-down plugin: perfect detail and completely answered comments. Oh, by the way, one problem obstructed me for a long time until I get the key word “QuartzCore framework” here from your answer. Thanks a lot!

  • Joakim Astrom

    Hi! 
    Great article!
    I got a few lines of code to support UIWebView without “Pull to refresh a UIWebView”.  Since a WebView has a scrollview, to access by property, I created “overload” constructors. Both is calling your constructor, which I renamed initView and takes 2 args instead of one. See code below
     
    – (id)initWithWebView:(UIWebView *)webView {
        CGRect frame = CGRectMake(0.0f, 0.0f – webView.bounds.size.height, webView.bounds.size.width, webView.bounds.size.height);
     
        return [self initView:webView.scrollView :frame];
     
    }
    – (id)initWithScrollView:(UIScrollView *)scroll {
        CGRect frame = CGRectMake(0.0f, 0.0f – scroll.bounds.size.height, scroll.bounds.size.width, scroll.bounds.size.height);
        return [self initView:scroll :frame];
    }
     
    // The method originally called – (id)initWithScrollView:(UIScrollView *)scroll
    – (id)initView:(UIScrollView *)scroll : (CGRect) frame{
     
        if ((self = [super initWithFrame:frame])) {
            scrollView = scroll;
            [scrollView addObserver:self forKeyPath:@”contentOffset” options:NSKeyValueObservingOptionNew context:NULL];
     
    ..


    return self;
    }
     

  • DanBrooke

    I’ve looked and looked for a step-by-step tutorial and this was PERFECT!  Thank you so much for taking the time to post this!

  • blueobaid

    This is a perfect tutorial thank you so much.!

  • cagvcr26

    Hello, one question… this code has a some kind of license??? Because i need a pull to refresh for an app in the company that i work, but i need to know if this code has license to commercial use. Please is urgent!! Thanks a lot!!

    • http://sonnyparlin.com sonnyparlin

      @cagvcr26 It’s open source, so you can use it freely on your commercial project.

  • TedW.Bendixson

    I haven’t used this yet, but I really love you took so much work out of it for me. This is what iOS modules should be!

  • TedW.Bendixson

    Okay. I’m just going to say this right now. I have never, not once, in my two years as an iOS developer run into such a neatly packaged module with such clear documentation. If you ever make it out to Breckenridge Colorado, I owe you a few beers. You’ve saved me what easily could have been hours of frustration.
     
    Thank you so much!

    • http://sonnyparlin.com sonnyparlin

      @TedW.Bendixson Word!

  • bitsdisasters

    Thank you very much. You saved my day. It works like a charm! :D

  • bitsdisasters

    It worked for me fine and I’m so glad for it but I have one question: what about timeout?. How to manage that event. Would it call finish with error delegate? Thanks

  • BobvanHees

    Thank you this did work great!

  • IuriMatsuura

    Sony,in iOS 6 I the view doesn’t change its state. Any solution?

  • IuriMatsuura

    Sony,in iOS 6  the view doesn’t change its state. Any solution?

    • http://sonnyparlin.com sonnyparlin

      @IuriMatsuura Can you provide a specific problem? It’s been running on iOS 6 fine for me…

  • AllDmeat

    Thank you for such a great work, everything works just awesome. But I want to add your PullToRefresh to simple UIView with UIScrollView inside. After few hours of my attempts I got nothing.
    I’m just a beginner, yes. And I don’t know why it doesn’t work for me – because of my wrong code or because it just can’t. And of course, it would be just awesome for me and many other people if You will include another few rows of code in your tutorial.
    Thank You a lot :)

    • http://sonnyparlin.com/ adminjeremy

      @AllDmeat I’m planning on doing this for one of my own projects, stay posted.

  • AllDmeat

    Thank you for such a great work, everything works just awesome. But I want to add your PullToRefresh to simple UIView with UIScrollView inside. After few hours of my attempts I got nothing.
    I’m just a beginner, yes. And I don’t know why it doesn’t work for me – because of my wrong code or because it just can’t. And of course, it would be just awesome for me and many other people if You will include another few rows of code in your tutorial.
    Thank You a lot :)

  • SwapnilGodambe

    Thanks

  • SwapnilGodambe

    Thanks Man !
     You made my work interesting ..

  • PhillyKetelcap

    how do i get the form to stay in “Loading” i was trying with sleep(1) but it didnt work!

  • PhillyKetelcap

    how do i get the view to stay in loading?
    i was trying it with sleep(1) but that didnt work!
     
    next thing i am getting a waring:sending ‘myViewController’ *const __strong to parameter of incompatible type id <pulltorefreshviewdelegate> 
    Thanks a lot

  • PhillyKetelcap

    solved the 2nd one! forgott the delegate in the .h file! :)

  • Mackey18

    Awesome code, good job. I’m having a small problem on my UITableView however. If only part of the PullToRefresh is showing while loading it plays havok with any section titles. They seem to scroll to where the bottom of the PullToRefresh would be, if it were fully on screen, creating an interesting effect. Is there anyway around this/fix? Regards, Mike. Only occurs on iOS6 by the way, doesn’t appear to happen on iOS 5.

  • Mackey18

    Fixed, simply change the PullToRefreshViewStateLoading case to:
     
    case PullToRefreshViewStateLoading:
    statusLabel.text = self.text;
    [self showActivity:YES animated:YES];
                [self setImageFlipped:NO];
                scrollView.contentInset = UIEdgeInsetsMake(60.0f, 0.0f, 0.0f, 0.0f);
                if (scrollView.contentOffset.y > -60.0 && scrollView.contentOffset.y < 0.0) {
                    [self.scrollView setContentInset:UIEdgeInsetsMake(-scrollView.contentOffset.y, 0.0, 0.0, 0.0)];
                }

  • ElangoBalusamy

    Thank you, works like a charm