Giter VIP home page Giter VIP logo

sspulltorefresh's Introduction

SSPullToRefresh

Version Carthage compatible CocoaPods compatible

There are dozens of pull to refresh views. I've never found one I'm happy with. I always end up customizing one, so I decided to write one that's highly customizable. You can just write your content view and forget about the actual pull to refresh details.

If you're using SSPullToRefresh in your application, add it to the list.

Example Usage

// If automaticallyAdjustsScrollViewInsets is set to NO:
- (void)viewDidLoad {
   [super viewDidLoad];
   self.pullToRefreshView = [[SSPullToRefreshView alloc] initWithScrollView:self.tableView delegate:self];
}

// If automaticallyAdjustsScrollViewInsets is set to YES:
- (void)viewDidLayoutSubviews {
   if(self.pullToRefreshView == nil) {
      self.pullToRefreshView = [[SSPullToRefreshView alloc] initWithScrollView:self.tableView delegate:self];
   }
}

- (void)viewDidUnload {
   [super viewDidUnload];
   self.pullToRefreshView = nil;
}

- (void)refresh {
   [self.pullToRefreshView startLoading];
   // Load data...
   [self.pullToRefreshView finishLoading];
}

- (void)pullToRefreshViewDidStartLoading:(SSPullToRefreshView *)view {
   [self refresh];
}

I generally make a property called loading in my view controller and just set that to YES inside refresh. Then in my custom setter, return if it's already YES. When it changes states, it will call startLoading and make the network call. Then when the network activity finishes, it will set it to NO and the customer setter handles calling finishLoading and doing whatever else.

The fine folks at NSScreencast have an excellent episode on SSPullToRefresh and even implementing a custom content view with Core Graphics. Check it out.

Customizing

SSPullToRefresh view is highly customizable. All of the pulling logic, animations, etc are wrapped up for you in SSPullToRefreshView. It doesn't have any UI. Its contentView handles displaying the UI. By default, it sets up an instance of SSSimplePullToRefreshContentView as the contentView.

Provided Content Views

SSPullToRefreshDefaultContentView and SSPullToRefreshSimpleContentView are provided by SSPullToRefresh. By default SSPullToRefreshDefaultContentView is used if you do not provide a content view. To use the provided simple content view, simply set it:

pullToRefreshView.contentView = [[SSPullToRefreshSimpleContentView alloc] initWithFrame:CGRectZero];

Custom Content Views

You can simply subclass SSPullToRefreshDefaultContentView or implement your own view that conforms to SSPullToRefreshContentView. You must implement the following method:

- (void)setState:(SSPullToRefreshViewState)state withPullToRefreshView:(SSPullToRefreshView *)view

This method will get called whenever the state changes. Here are the possible states. It is recommended to implement UI for most of the states, but you can do whatever you want.

  • SSPullToRefreshViewStateNormal (recommended) — Most will say "Pull to refresh" in this state
  • SSPullToRefreshViewStateReady (recommended) — Most will say "Release to refresh" in this state
  • SSPullToRefreshViewStateLoading (recommended) — The view is loading
  • SSPullToRefreshViewStateClosing (optional) — The view has finished loading and is animating closed

You may also optionally implement this method:

- (void)setLastUpdatedAt:(NSDate *)date withPullToRefreshView:(SSPullToRefreshView *)view

Adding To Your Project

Carthage is the recommended way to install SSPullToRefresh. Add the following to your Cartfile:

github "soffes/sspulltorefresh"

You can also install with CocoaPods:

pod 'SSPullToRefresh'

For manual installation, I recommend adding the project as a subproject to your project or workspace and adding the framework as a target dependency.

Thanks

I took some inspiration from PullToRefreshView by chpwn, which is based on EGOTableViewPullRefresh, which is inspired by Tweetie's pull to refresh by Loren Brichter. And around we go.

Enjoy.

sspulltorefresh's People

Contributors

adamvaughan avatar ademozgur avatar alanzeino avatar blommegard avatar calebd avatar f1fe avatar felipemathies avatar grantjk avatar gstjohn avatar hwaxxer avatar joshavant avatar jurysch avatar kvnsmth avatar maoyama avatar mspasov avatar nickynick avatar soffes avatar tflhyl avatar yas375 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sspulltorefresh's Issues

View left expanded if pullToRefreshViewShouldStartLoading returns NO

You need to change the end of the observeValueForKeyPath body so that expanded isn't always passed true, e.g.

BOOL expand = YES;
// Ask the delegate if it's cool to start loading
if ([_delegate respondsToSelector:@selector(pullToRefreshViewShouldStartLoading:)]) {
    if (![_delegate pullToRefreshViewShouldStartLoading:self]) {
        // Animate back to normal since the delegate said no
        newState = SSPullToRefreshViewStateNormal;
                    expand = NO;
    }
}

// Animate to the new state
[self _setState:newState animated:YES expanded:expand completion:nil];

Load repeat records

I think it need set one lock when pull to refresh, or else , it get repeat records from server.

Strange Animation

I have a strange performance in the header animation.
When the number of cells are few, eg five, the animation is strange.The header automaticly jumps up and after makes the down animation and up again.

Thanks

Delegate Callback Behavior

Programatic invocations of startLoading should not cause the delegate method pullToRefreshViewDidStartLoading: to be called. This should only be called on user-initiated events.

The example in SSPullToRefreshView.h is a good example of this issue:

- (void)refresh {
   [self.pullToRefreshView startLoading];
   // Load data...
   [self.pullToRefreshView finishLoading];
}

- (void)pullToRefreshViewDidStartLoading:(SSPullToRefreshView *)view {
   [self refresh];
}

Consider the following scenario given the above code:

  • View controller is sent viewDidAppear:
  • refresh is called to trigger a first load
  • startLoading is called so that the refresh control reflects the current loading state
  • pullToRefreshViewDidStartLoading: is called during the state transition
  • refresh is called again

SSPullToRefreshView prevents that from continuing in an infinite loop, but I now have multiple instances of refresh running for what should have been a single invocation.

The only way I have found around this is to override startLoading and wrap the call to super by temporarily removing the delegate. Alternatively, any consumer is required to track loading state to prevent a single invocation of refresh from firing multiple loads.

You continue to rock, Sam Soffes

I was raging all day (still am) on a very weird UICollectionView animation bug.

As a side project, I realized that our pull-to-refresh has been shoved under our navigationbar (which animates in and out - which is causing the animation bug, incidentally).

At first I was like awww wtf, who is messing with the insets what's going on!? (having been raging for so long, it was impossible to turn off). SSPullToRefresh!? Bah!

Dropped into the code, saw defaultContentInset, set it to the new values, and shit just works.

👏 👏 👏

Nice work. Thanks for, at least, making the end of my day enjoyable. Tomorrow I have to get back to fixing this animation thing, but that's another day!

Swift compat?

Hi,

What about Swift compatibility? it works fine?

Semantic version tags

I’ve recently added SSPullToRefresh to the CocoaPods package manager repo.

CocoaPods is a tool for managing dependencies for OSX and iOS Xcode projects and provides a central repository for iOS/OSX libraries. This makes adding libraries to a project and updating them extremely easy and it will help users to resolve dependencies of the libraries they use.

However, sspulltorefresh doesn't have any version tags. I’ve added the current HEAD as version 0.0.1, but a version tag will make dependency resolution much easier.

Semantic version tags (instead of plain commit hashes/revisions) allow for resolution of cross-dependencies.

In case you didn’t know this yet; you can tag the current HEAD as, for instance, version 1.0.0, like so:

$ git tag -a 1.0.0 -m "Tag release 1.0.0"
$ git push --tags

-pullToRefreshViewDidFinishLoading is called before the animation starts

Hi Sam,

When SSPullToRefreshView's -finishLoading is called, SSPullToRefreshView's calls the delegate method -pullToRefreshViewDidFinishLoading before the animation is finished.
It would be very convenient to have a delegate method that is called after the animation has finished.

Thanks for your great work,
Laurin

How to expand manually

Hi,

I'm looking for a way to programmatically show the refresh control so it's visible when opening my view controller. Any way to do this? I couldn't find any yet.

Thanks!

Unrecognized selector on iOS6

Any idea why I might be getting:

-[SSPullToRefreshView _update]: unrecognized selector sent to instance 0xd0ca5a0

at this line in viewDidLoad:

self.refreshControl = [[SSPullToRefreshView alloc] initWithScrollView:self.tableView delegate:self];

Thanks!

Pull progress > 1.0 is not reported.

I see in 1.2.2, the call that clamped the scroll progress to < 1.0 is gone, but it still isn't being sent. In the KVO callback, the setProgress: call doesn't happen if the state is .Ready, which it is if the offset is greater than the expanded height. Not sure what the best solution is.

ask delegate for lastUpdatedAt after finishLoading

Hello @samsoffes !

At first, thank you for your library! It's really simple ti use =)

I'm using this lib in my current project and have question about refreshing lastUpdatedAt. I found comment to pullToRefreshViewLastUpdatedAt: method:

... This will get called when it finishes loading...

So, I assume that my delegate should receive this method after I call [self.pullToRefreshView finishLoading]; but it doesn't wirk now.

Now I've implemented one more method in my delegate to manually ask pulltoRefresh to refresh date:

- (void)pullToRefreshViewDidFinishLoading:(SSPullToRefreshView *)view {
    [view refreshLastUpdatedAt];
}

But maybe better to ask delegate for lastUpdatedAt date when we finish loading?

I will be glad to send you a pull request if you agree with it =)

Thanks

show time as last updated at

In our current project we decided to show time as last updated at because we think that it's more useful than just a date. We could refresh timeline lots of times a day.

So I've implemented it by adding subclass for SSPullToRefreshDefaultContentView with one redefined method:

- (void)setLastUpdatedAt:(NSDate *)date withPullToRefreshView:(SSPullToRefreshView *)view {
    static NSDateFormatter *dateFormatter = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        dateFormatter = [[NSDateFormatter alloc] init];
        dateFormatter.dateFormat = @"HH:mm:ss";
    });
    self.lastUpdatedAtLabel.text = [NSString stringWithFormat:
                                    @"Last Updated: %@",
                                    [dateFormatter stringFromDate:date]];
}

It works and everything is fine =) I just would like to give a propose to change default implementation also to show time instead of date.
@samsoffes I will be happy to send you a pull request if you will apply this idea =)

thanks)

Animation glitch upon touch release when state == SSPullToRefreshViewStateReady

I'm using a custom view that conforms to SSPullToRefreshContentView, if that makes a difference. But when I drag downward until the state is SSPullToRefreshViewStateReady, and release the touch from a static velocity (i.e. don't "fling" the scrollview downward) the content view seems to instantly shift upward by about 20px before smoothly transitioning to the correct content inset. For me, using UIScrollView delegate methods instead of KVO solves the problem. Might be something to look into.

sectionIndexTitles jumps up and down when loading

Hi, @soffes.

First of all, I must say I've been using SSPullToRefresh for quite some time now and I love it. Thanks for a great component.

Recently, I ran into an issue, though. I tried attaching SSPullToRefresh to a UITableView that displays sectionIndexTitles (the index on the right side, for quickly navigation between sections).

Everything works as usual, but when SSPullToRefresh starts loading and the table contentInset is adjusted in _setContentInsetTop:, the positioning of index titles is affected, making the menu jump up and down. Although this happens only once per refresh, it doesn't make up for a great user experience.

Is there a known or proposed solution to make things work with tableViews displaying sectionIndexTitles?

Disable the SSPullToRefresh

Hi, first of all nice work around this!

I am using SSPullToRefresh in one of my projects, but now i face a simple problem, i want to disable the refresh for a moment ( view in edit mode ) and i can't view the way to do it.

Any suggestions?

Regards from Portugal.

iOS 7

Hey folks, thanks a bunch for this its been super useful.

Just wondering what I need to do to get this working with iOS 7?

After SSPullToRefresh finishes loading it seems to mess with (reduces?) the height of the scrollView.

Rare SIGSEGV

Getting the following error very rarely with no other information:

Exception Type: SIGSEGV Code: SEGV_ACCERR

Stack:

SSPullToRefreshView.m line 207
+[UIView(UIViewAnimationWithBlocks) _setupAnimationWithDuration:delay:view:options:animations:start:completion:] + 508
+[UIView(UIViewAnimationWithBlocks) animateWithDuration:delay:options:animations:completion:] + 60
SSPullToRefreshView.m line 206

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.