UPDATE: 3/23/2013 Discussion for PullToRefresh has been moved to its own forum for easier management. Old comments have been left in place for people to view.
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 [email protected] 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:
|
1 2 3 |
#import "PullToRefreshView.h" @interface YourViewController : UITableViewController |
Now add an iVar to your viewcontroller’s .m file:
|
1 2 3 4 |
@implementation RootViewController { PullToRefreshView *pull; } |
Then add the following to your UITableViewController in ViewDidLoad:
|
1 2 3 |
pull = [[PullToRefreshView alloc] initWithScrollView:(UIScrollView *) self.tableView]; [pull setDelegate:self]; [self.tableView addSubview:pull]; |
Next, you simply add the delegate method for when the user pulls to refresh:
|
1 2 3 4 |
- (void)pullToRefreshViewShouldRefresh:(PullToRefreshView *)view; { [self reloadTableData]; } |
Finally, in your reloadTableData method, call finish
|
1 2 3 4 5 6 7 |
-(void) reloadTableData { // call to reload your data ... [self.tableView reloadData]; [pull finishedLoading]; } |
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.
|
1 2 3 4 |
- (void)pullToRefreshViewShouldRefresh:(PullToRefreshView *)view; { [self performSelectorInBackground:@selector(reloadTableData) withObject:nil]; } |
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
|
1 2 3 4 |
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(foregroundRefresh:) name:UIApplicationWillEnterForegroundNotification object:nil]; |
Then add this to your UITableView:
|
1 2 3 4 5 6 |
-(void)foregroundRefresh:(NSNotification *)notification { self.tableView.contentOffset = CGPointMake(0, -65); [pull setState:PullToRefreshViewStateLoading]; [self performSelectorInBackground:@selector(reloadTableData) withObject:nil]; } |
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:
|
1 |
UIScrollView* currentScrollView; |
Next, in ViewDidLoad make the UIWebView a delegate to itself and give it a tag:
|
1 2 3 |
// Make webView a delegate to itself [webView setDelegate:self]; webView.tag = 999; |
Now add the following to your ViewDidLoad:
|
1 2 3 4 5 6 |
for (UIView* subView in webView.subviews) { if ([subView isKindOfClass:[UIScrollView class]]) { currentScrollView = (UIScrollView *)subView; currentScrollView.delegate = (id) self; } } |
Now you can set up your PullToRefreshView scrollView and add it to the webView:
|
1 2 3 4 5 6 |
// Set up Pull to Refresh code PullToRefreshView *pull = [[PullToRefreshView alloc] initWithScrollView:currentScrollView]; [pull setDelegate:self]; pull.tag = 998; [currentScrollView addSubview:pull]; [self.view addSubview: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:
|
1 |
@interface YourViewController : UIViewController |
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:
|
1 2 3 |
-(void)pullToRefreshViewShouldRefresh:(PullToRefreshView *)view { [(UIWebView *)[self.view viewWithTag:999] reload]; } |
Then in your webViewDidFinishLoad method, add the following:
|
1 2 3 4 |
- (void)webViewDidFinishLoad:(UIWebView *)wv { [(PullToRefreshView *)[self.view viewWithTag:998] finishedLoading]; } |
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.
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?
Change the property in PullToRefreshView.h to this:
@property (nonatomic, strong) id<PullToRefreshViewDelegate> delegate;
So change it from “assign” to “strong”.
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.
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.
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: 0×0, 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?
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];
}
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 0×8249920: Observer: 0x82cf3c0, Key path: contentOffset, Options: Context: 0×0, 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?
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!
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!
No problem, glad you got it working!
Pingback: iOS: Pull To Refresh error
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?
I haven’t seen that, but that’s probably because I’ve never set up a webView to scroll horizontally… Sorry.
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.
Can you provide a screenshot so I can what we’re talking about here?
FYI, fixed this issue. Details here:
https://github.com/chpwn/PullToRefreshView/issues/4
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!
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!
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?
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!
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?
Yes, with Automatic Reference Counting (ARC) all memory management is handled for you, so no need to release, retain, etc…
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. =)
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.
Does it crash or just hang?
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.
Are you sure -finishedLoading is being called?
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,
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…
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.
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.
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
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.
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);
Thank you! Excellent, clear writeup.
I’m confused why your fork is not an actual fork of the original project.
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 ).
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.
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.
Have you tried setting a breakpoint?
I just noticed this feature
while testing on my device. Debugging will be my next step! Thanks for the prompt response.
Guys, is there a solution for this? I’m experiencing the same, and that kills such a great addition to the app.
@Skrew It seems it’s not a problem of the pullToRefresh stuff, but a problem of mine, I returned nil to
cellForRowAtIndexPath sometimes which caused this.
Dude!!!! Awesome!!! Thank you so much!!!!!!!!
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: 0×0, Property: 0x1b87c0>
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.
I’ll investigate. I guess another option is to use the original version and disable ARC on PullToRefreshView as stated in this article: http://mobile.dzone.com/articles/arc-support-without-branching
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
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.
Sorry, you will have to post some code… use pastebin (http://pastebin.com/) and then provide a link to your paste.
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?
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
You have to remove all references to retain and release from your code.
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
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!
hehe nevermind
After doing a google search on my error, got it to work!
Awesome man, Great help!
@Anthony, try doing this:
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self forKeyPath:@”contentOffset”];
}
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 0×1583901 0xf59c 0x2026e3d 0xd3bcbe 0xee30be 0xee33c7 0xee3436 0xc93e49 0xc93f34 0x57fb54 0×2287509 0x1b61803 0x1b60d84 0x1b60c9b 0x24167d8 0x241688a 0xc63626 0x24dd 0×2445)
terminate called throwing an exception(lldb)
Fixed it by using this
Fixed it by adding the following dealloc method
– (void)dealloc
{
[self.tableView removeObserver:pull forKeyPath:@"contentOffset"];
}
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?
Nothing at all, it’s open source.
Much appreciated!!! This works amazing and took 5 minutes to implement.
Glad I could help, I just took what I found out there, modified it a little and tutorialized it somewhat.
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?
Never mind I got it working. I just changed where I call the [pull finishedLoading];
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?
I am also missing the arrow graphic… everything else appears to work. Any ideas?
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)
I solved the problem by adding PullToRefreshView.m to the list of file to compile in the build phase.
which code highlighter plugin are you using man?
Crayon Syntax Highlighter
http://ak.net84.net/projects/crayon-syntax-highlighter/
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)
Looks like you need to link to the QuartzCore framework.
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:)
Figured out the issue! I was clearing my array when I did a reload. Thanks again for all the help! Excellent plugin!!
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.
Perhaps you should use performSelectorOnMainThread
You could always wait until you’re inside the thread you want to be in and then send to background…
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
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!
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.
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
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
Thanks for this, it works perfectly and a novice like myself can understand whats happening!
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.
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?
Cameron,
Send me your code and I’ll have a look… [email protected].
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.
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?
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.
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.
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.
Are you calling [pull finishedLoading]; after your data gets updated?
@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?
@arslanjaved Sorry, no… I don’t even know what EgoImageLoading is.
@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!
@arslanjaved Here is a piece of code from one of my projects that does exactly that.
https://gist.github.com/3650086
@sonnyjitsu GCD is something i haven’t learnt and its complicated. Anyways thanks for sharing it
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!
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;
}
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!
This is a perfect tutorial thank you so much.!
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!!
@cagvcr26 It’s open source, so you can use it freely on your commercial project.
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!
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!
@TedW.Bendixson Word!
Thank you very much. You saved my day. It works like a charm!
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
Thank you this did work great!
Sony,in iOS 6 I the view doesn’t change its state. Any solution?
Sony,in iOS 6 the view doesn’t change its state. Any solution?
@IuriMatsuura Can you provide a specific problem? It’s been running on iOS 6 fine for me…
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
@AllDmeat I’m planning on doing this for one of my own projects, stay posted.
@adminjeremy any update?
@AllDmeat Sorry not yet…
@adminjeremy thanx anyway
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
Thanks
Thanks Man !
You made my work interesting ..
how do i get the form to stay in “Loading” i was trying with sleep(1) but it didnt work!
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
solved the 2nd one! forgott the delegate in the .h file!
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.
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)];
}
Thank you, works like a charm
Can some please help me with it,
I still cant get it to work. I have done everything you said. I am not able to keep the view in the Loading Part. Even if I do a loop right below the section
// call to reload your data …
-(void) reloadTableData
{ // call to reload your data …
[self.tableView reloadData];
[pull finishedLoading];}
I wont show the loading view, what am I doing wrong, please would be great if someone could help. THX
@PhillyKetelcap Send me your code and I’ll take a look. ([email protected])
Special Thanks to Sonnyparlin! He was able to solve my Problem with in 5 min! Great work thank you for your great help!
By far the best approach, many other approaches would want you to extend either the TableViewController or the Table view, but this way gives you freedom of using your tableviews and its controllers the way you want and yet achieve the functionality.
Hey and thanks a bunch with a whole lot of your favorite things for this library, it’s definitely the most useful and easy to implement library that I’ve come across.
One question I have is if it’s possible to simulate the drag and release actions programmatically, i.e. when I enter a new screen, if it’s possible for the header to scroll and change it’s state by itsef (with some animation duration), in order to make it obvious to the user that the app has this functionality.
I’ve tried tinkering with the contentInsets/Offsets and applying the PullToRefreshViewStateLoading after a certain delay but I’m having trouble in moving the PullToRefreshViewState through all the states. Is there any way that this can be accomplished?
Thanks again and have a great day.
@SebastianVancea Look in the “Couple of Tricks” section of the tutorial, you could rework that to work for your needs.
@sonnyjitsu First of all, thanks for your answer, I appreciate it.
Second of all, I have obviously tried the tricks before posting, and I had no problem bringing the header down, but what I was asking about the scrolling simulation, and a way to make the setStatus function work within an animation block.
I’ll keep trying and I’ll post the results if I find a way. Thanks anyway.
Hi,
thank you for the great lib and the tutorial. It works nice.
Unfortunately i have the following problem in iOS 6. In the state, when the activity-indicator is spinning, the shadow in the pull-to-refresh-view is disappearing.
Any idea?
Thank you
Volker