Code Monkey home page Code Monkey logo

pulltorefresh's Introduction

Customizable PullToRefresh

This component implements pure pull-to-refresh logic and you can use it for developing your own pull-to-refresh animations, like this one.

Yalantis

Requirements

  • iOS 8.0+
  • Swift 5.0 (v 3.2+)
  • Swift 4.2 (v 3.1+)
  • Swift 3 (v. 2.0+)
  • Swift 2 (v. 1.4)

Installing

use_frameworks!
pod 'PullToRefresher'
github "Yalantis/PullToRefresh"

Usage

At first, import PullToRefresh:

import PullToRefresh

The easiest way to create PullToRefresh:

let refresher = PullToRefresh()

It will create a default pull-to-refresh with a simple view which has single UIActivitiIndicatorView. To add refresher to your UIScrollView subclass:

tableView.addPullToRefresh(refresher) {
    // action to be performed (pull data from some source)
}

⚠️ Don't forget to remove pull to refresh when your view controller is releasing. ⚠️

deinit {
    tableView.removeAllPullToRefresh()
}

After the action is completed and you want to hide the refresher:

tableView.endRefreshing()

You can also start refreshing programmatically:

tableView.startRefreshing()

But you probably won’t use this component, though. UITableViewController and UICollectionViewController already have a simple type of refresher. It’s much more interesting to develop your own pull-to-refresh control.

Usage in UITableView with sections

Unfortunaly, UITableView with sections currently not supported. But you can resolve this problem in two steps:

  1. Create you own PullToRefresh (see instructions below).
  2. Set its shouldBeVisibleWhileScrolling property to true. It makes you PullToRefresh always visible while you're scrolling the table.

⚠️ By default PullToRefresh has transparent background which leads to unwanted overlapping behavour. ⚠️

Disable/Enable

You can disable/enable refresher in runtime:

yourRefresher.setEnable(isEnabled: false)

Creating custom PullToRefresh

To create a custom refresher you would need to initialize PullToRefresh class with two objects:

  • refreshView is a UIView object which will added to your scroll view;
  • animator is an object which will animate elements on refreshView depending on the state of PullToRefresh.
let awesomeRefresher = PullToRefresh(refresherView: yourView, animator: yourAnimator)

Steps for creating custom PullToRefresh

  1. Create a custom UIView with *.xib and add all images that you want to animate as subviews. Pin them with outlets:
class RefreshView: UIView {

    @IBOutlet private var imageView: UIImageView!
  
    // and others
}
  1. Create an Animator object that conforms RefreshViewAnimator protocol and can be initialized by your custom view:
class Animator: RefreshViewAnimator {

    private let refreshView: RefreshView
    
    init(refreshView: RefreshView) {
        self.refreshView = refreshView
    }

    func animate(state: State) {
        // animate refreshView according to state
    }
}
  1. According to RefreshViewAnimator protocol, your animator should implement animateState method. This method is get called by PullToRefresh object every time its state is changed. There are four states:
public enum State: Equatable, CustomStringConvertible {
    
    case initial
    case releasing(progress: CGFloat)
    case loading
    case finished
}
  • Initial - refresher is ready to be pulled.
  • Releasing - refresher is in the process of releasing (by a user or programmatically). This state contains a double value which represents releasing progress from 0 to 1.
  • Loading - refresher is in the loading state.
  • Finished - loading is finished.

Depending on the state that your animator gets from the PullToRefresh, it has to animate elements in refreshView:

func animate(state: State) {
    switch state {
      case .initial: // do inital layout for elements
      case .releasing(let progress): // animate elements according to progress
      case .loading: // start loading animations
      case .finished: // show some finished state if needed
    }
}

Place the magic of animations insted of commented lines.

  1. For the convitience sake you can sublass from PullToRefresh and create separate class for your refresher:
class AwesomePullToRefresh: PullToRefresh {

    convenience init() {
        let refreshView = Bundle(for: type(of: self)).loadNibNamed("RefreshView", owner: nil, options: nil)!.first as! RefreshView
        let animator = Animator(refreshView: refreshView)
        self.init(refreshView: refreshView, animator: animator)
    }
}
  1. Finally, add a refresher to a UIScrollView subclass:
tableView.addPullToRefresh(refresher) {
    // action to be performed (pull data from some source)
}

Have fun! :)

Let us know!

We’d be really happy if you sent us links to your projects where you use our component. Just send an email to [email protected] And do let us know if you have any questions or suggestion regarding the animation.

P.S. We’re going to publish more awesomeness wrapped in code and a tutorial on how to make UI for iOS (Android) better than better. Stay tuned!

License

The MIT License (MIT)

Copyright © 2018 Yalantis

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

pulltorefresh's People

Contributors

aeugene avatar angcosmin avatar balestrapatrick avatar christie-alphero avatar chuynadamas avatar daisuke310vvv avatar dataich avatar egorsobko avatar esetnik avatar gktoken avatar gorbannastya avatar jakubmazur avatar katerynazaikina avatar krzyzanowskim avatar madsbogeskov avatar mamouneyya avatar marvinnazari avatar maximletushov avatar mrcompoteee avatar mysteriousdeveloper avatar naeemshaikh90 avatar nolanw avatar plu avatar pravdaevgen avatar rnkyr avatar serejahh avatar sergey-prikhodko avatar slizeray avatar tripolev avatar vodolazkyi 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pulltorefresh's Issues

Compatibility with ScrollView?

Hello,

Thanks for your awesome Framework.

I tried to use PullToRefresh with a simple UIScrollView, the refresher appeared but there are problems with animations (the progress is always 1 and the refresher doesn't wait before disappearing).
The exact same code with an UITableView works like a charm.

Is it a framework limitation or do I have a problem with my code? I know that there are limitations with the native UIRefreshControl so maybe you have the same.
If it's a limitation maybe you should remove the extension from UIScrollView and add it to UITableView and UICollectionView instead.

Kind regards,
Denis

dyld: Library not loaded for Swift 2.3

Got an issue on Xcode8 for Swift 2.3

dyld: Library not loaded: @rpath/PullToRefresh.framework/PullToRefresh
Referenced from: /Users/liangwang/Library/Developer/CoreSimulator/Devices/66255D64-7B2F-45B9-8508-9399AF63F9F0/data/Containers/Bundle/Application/A1AB80C4-7F6E-40E4-B5D1-AE4B301DB6EE/epcmobile-ios.app/epcmobile-ios
Reason: image not found

I have included library in Carthage with : github "Yalantis/PullToRefresh" ~> 1.4

NSInternalInconsistencyException bug

Report a bug

What did you do?

Crash would definitely be caused if you release the viewController that contains tableview and topPullToRefresh, while you are running your demo with an ipad2 ios9. In this case, calling removePullToRefresh() in deinit() is invalid. There would be some unknown reasons that may cause the delay of releasing topPullToRefresh rather than tableview, and the topPullToRefresh still keep observing tableview.

Crash Log:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'An instance 0x7e2cf200 of class UITableView was deallocated while key value observers were still registered with it. Current observation info: <NSKeyValueObservationInfo 0x7be86b20> (
<NSKeyValueObservance 0x7be844e0: Observer: 0x7d27d380, Key path: contentOffset, Options: <New: NO, Old: NO, Prior: NO> Context: 0x7d27d3ec, Property: 0x7bf74ff0>
<NSKeyValueObservance 0x7be854a0: Observer: 0x7d27d380, Key path: contentSize, Options: <New: NO, Old: NO, Prior: NO> Context: 0x7d27d3ec, Property: 0x7be854d0>
<NSKeyValueObservance 0x7be859b0: Observer: 0x7d27d380, Key path: contentInset, Options: <New: YES, Old: NO, Prior: NO> Context: 0x7d27d3ec, Property: 0x7be859e0>
<NSKeyValueObservance 0x7be864b0: Observer: 0x7be862d0, Key path: contentOffset, Options: <New: NO, Old: NO, Prior: NO> Context: 0x7be8633c, Property: 0x7bf74ff0>
<NSKeyValueObservance 0x7be86510: Observer: 0x7be862d0, Key path: contentSize, Options: <New: NO, Old: NO, Prior: NO> Context: 0x7be8633c, Property: 0x7be854d0>
<NSKeyValueObservance 0x7be86ca0: Observer: 0x7be862d0, Key path: contentInset, Options: <New: YES, Old: NO, Prior: NO> Context: 0x7be8633c, Property: 0x7be859e0>
)'

Your Environment

  • Swift version: Swift 3.0
  • iOS version: iOS9
  • Device: iPad2
  • Xcode version: Version 8.2.1 (8C1002)

Swift 2.3 + Swift 3.0

Hi!

I suggest to introduce two branches that works with swift 2.3 and swift 3.0.

Thanks
-Paolo

Opposite refresher is missing in a common scrolling case

Report

It can be reproduced in PullToRefreshDemo.xcodeproj

Report a bug

What did you do?

Pull down the table view, and don't fire the action of the top refresher, and hold the finger.
Scroll up the table view rapidly.
Go to the bottom of the table view.

What did you expect to happen?

The bottom refresher is existing.

What happened instead?

The bottom refresher is missing.

Your Environment

  • Version of the component: 3.1.0
  • Swift version: 4.2
  • iOS version: iOS 12.0.1
  • Device: iPhone X
  • Xcode version: 10.0 (10A255)
  • CocoaPods: 1.5.3

Project that demonstrates the bug

The PullToRefreshDemo.xcodeproj can reproduce it.

Advice

In the override open func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) of PullToRefresher.swift, I change some code in the first if part:
switch offset {
case 0 where (state != .loading): state = .initial
case -refreshViewHeight...0 where (state != .loading && state != .finished):
state = .releasing(progress: -offset / refreshViewHeight)

        case -1000...(-refreshViewHeight):
            if state == .releasing(progress: 1) && scrollView?.isDragging == false {
                state = .loading
            } else if state != .loading && state != .finished {
                state = .releasing(progress: 1)
            }
        case 0...1000:
            if state != .loading && state != .finished && state != .initial {
                state = .initial
            }
        default:
            break
        }

Memory leak

I'm using swift2.0 branch.
Steps to reproduce:

  1. Download demo project.
  2. Insert UIViewController between UINavigationController and sample ViewController
  3. Add button on new UIViewController and link it to sample ViewController, so now you can tap on button and push sample ViewController.
  4. Inside ViewController.swift add deinit method. You can add printing or use breakpoints.
  5. Run application and go to sample screen.
  6. Go back, sample should be deallocated, but no. You can comment addPullToRefresh method in viewDidAppear and repeat test and you will get deallocation.

Dyanmic Height issue

Re-opening issue #19

From previous last comment:
Hey @serejahh. I am not sure the expected behaviour from this, but the issue still exists for us.

What happens is the refresh view that we create is added behind the tableView and the height of that refresh view is not dynamic when scrolled past its original height.

Here is an example image from looking at the view layout.
screen shot 2016-08-09 at 16 29 21

Here is a video example:
http://quick.as/1Ov9HBr86

In our case we need the background colour of the tableview which can be seen at the top once scrolled past the height of the Refresh view. But we would expect the refresh view to dynamically change its height once past its original.

Could this be re-opened? Thanks

Blocking main thread while endRefreshing()

Hello,

If I triggered a pull-to-refresh request and then immediately start scrolling while the app fetches the new data, the table view will hang for a second or so once the endRefreshing() gets called. This provides a very bad indication to the user.

Custom RefreshView frame is not updated based on ScrollView width

Report a bug

What did you do?

Created a custom refreshview and animator and added it to the tableview.

    lazy var refresher: PullToRefresh = {
        let refreshView = WhiteLoadingIndicatorView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
        let animator = WhiteLoadingIndicatorAnimator(refreshView: refreshView)
        let refresher = PullToRefresh(refreshView: refreshView, animator: animator, height: 40, position: .top)
        return refresher
    }()
        tableView.addPullToRefresh(self.refresher, action: { [weak self] in
            print("Reload")
        })

Custom RefreshView and Animator:

import UIKit
import PullToRefresh

class WhiteLoadingIndicatorView: UIView {

    var indicator: UIActivityIndicatorView!
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }
    
    private func setup() {
        backgroundColor = .red
        indicator = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
        indicator.hidesWhenStopped = false
        indicator.startAnimating()
        addSubview(indicator)
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        indicator.center = CGPoint(x: bounds.midX, y: bounds.midY)
    }
}

class WhiteLoadingIndicatorAnimator: RefreshViewAnimator {
    
    private let refreshView: WhiteLoadingIndicatorView
    
    init(refreshView: WhiteLoadingIndicatorView) {
        self.refreshView = refreshView
    }
    
    func animate(_ state: State) {
        switch state {
        case .initial, .finished:
            refreshView.indicator.stopAnimating()
        case .releasing:
            break
        case .loading:
            refreshView.indicator.startAnimating()
        }
    }
}

What did you expect to happen?

RefreshView frame should be set to the with of the containing scrollview.

What happened instead?

Frame is set to 375 width once based on the storyboard viewcontroller size and never updated to 320 when the scrollview is resized to the screen size of the iPhone SE.

Your Environment

  • Version of the component: PullToRefresher 3.0.1
  • Swift version: 4
  • iOS version: 9.3
  • Device: iPhone Simulator 9.3 SE
  • Xcode version: 9.2
  • If you use Cocoapods: run pod env | pbcopy and insert here

Height didn't work when create a custom PullToRefresh.

public init(refreshView: UIView, animator: RefreshViewAnimator, height: CGFloat, position: Position) {     
        self.refreshView = refreshView        
        self.animator = animator
        self.position = position
 }

'height' seems like not being used.

Section header displaced

Report

screen shot 2017-04-16 at 00 37 34

Report a bug

What did you do?

Pull to refresh + some scroll

What did you expect to happen?

Normal sticky section header

What happened instead?

Section header displaced.
See screenshot.

Your Environment

  • Version of the component: ~> 2.0
  • Swift version: 3
  • iOS version: 9.3.5
  • Device: simulator 4s, 5
  • Xcode version: 8.3

Project that demonstrates the bug

import UIKit
import PullToRefresh

class YalantisController: UIViewController {
    
    @IBOutlet weak var tableView: UITableView!
    let dataSource = TableDataSource()
    let refresher = PullToRefresh()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        dataSource.tableView = tableView
        tableView.addPullToRefresh(refresher) {
            DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
                print("refreshData")
                self.dataSource.someArray = self.dataSource.someArray.reversed()
                self.tableView.endRefreshing(at: .top)
            }
        }
    }
    
    deinit {
        tableView.removePullToRefresh(tableView.topPullToRefresh!)
        print(self.classForCoder)
    }
}


import UIKit

class TableDataSource: NSObject {
    
    @IBOutlet weak var tableView: UITableView! {
        didSet { tableView.dataSource = self }
    }
    
    var someArray: [Int] = [1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 1] {
        didSet { tableView.reloadData() }
    }
}
extension TableDataSource: UITableViewDataSource {
    func numberOfSections(in tableView: UITableView) -> Int {
        return 4
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return someArray.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = String(someArray[indexPath.row])
        return cell
    }
    
    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return "Section \(section + 1)"
    }
}

Getting Crash

Report

Please add images.

Screen Shot 2019-11-23 at 12 22 04 PM

Report a bug

Please describe what you want to add to the component.
Getting crash.

Step 1 - Working fine pull to refresh
Step 2 - popup
Step 3 - tap Humberger menu and getting Crash

on
deinit {
tableView.removeAllPullToRefresh()
}
I deceleader on ViewDidLoad

Broken in XCode 9 + iOS 11

Report

After updating XCode to 9.x this library seems to be broken. I add a .top refresher and experience the progress let starting at 0.6 when you reach the top of the scroll view and start pulling. Aside from that it is buggy in general when pulling down and releasing. The content insets no longer match when it returns to a normal state.

I should mention this is with a Custom Animation, not the default one, so the demo project still seems to work. Also it's within a UITableViewController, not a UIViewController with a UITableView inside it as in the demo project.

I previously submitted a bug report where I manage to fix some of this weird behaviour with automaticallyAdjustsScrollViewInsets and contentInsets, but it doesn't work anymore. I think Apple may have changed some logic with UIEdgeInsets for UITableViewControllers. I can't really make it work and I'm stuck. Currently my top inset logs out as 0 even though it's clearly 64 (height of navigation bar). I think this messes with all the calculations the library does.

Your Environment

  • Version of the component: 2.0.2
  • Swift version: 3
  • iOS version: 11
  • Device: iPhone 6S
  • Xcode version: 9
  • If you use Cocoapods: _run pod env | pbcopy and insert here:

Stack

   CocoaPods : 1.2.1
        Ruby : ruby 2.0.0p648 (2015-12-16 revision 53162) [universal.x86_64-darwin16]
    RubyGems : 2.0.14.1
        Host : Mac OS X 10.12.6 (16G29)
       Xcode : 9.0 (9A235)
         Git : git version 2.13.5 (Apple Git-94)
Ruby lib dir : /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib
Repositories : master - https://github.com/CocoaPods/Specs.git @ ae7c17ebfbc1d62bdd7f9b52982ea9384e28f173

Installation Source

Executable Path: /usr/local/bin/pod

Plugins

cocoapods-deintegrate : 1.0.1
cocoapods-plugins     : 1.0.0
cocoapods-search      : 1.0.0
cocoapods-stats       : 1.0.0
cocoapods-trunk       : 1.2.0
cocoapods-try         : 1.1.0

Podfile

# Uncomment this line to define a global platform for your project
platform :ios, '9.0'

target 'nyx-public' do
  # Comment this line if you're not using Swift and don't want to use dynamic frameworks
  use_frameworks!

  # Pods for nyx-public
  pod 'PullToRefresher'   
  pod 'Firebase/Messaging'
  pod 'Firebase/Core'
  pod 'SwiftSpinner'
  pod 'FontAwesome.swift'  
  pod 'FacebookCore'
  pod 'FacebookLogin'
  pod 'KeychainAccess'
  pod 'Alamofire'
  pod 'QRCode'
  pod 'SwiftyJSON'
  pod 'AFNetworking'
  pod 'RoundedSwitch'

  pod 'Spring', :git => 'https://github.com/MengTo/Spring.git', :branch => 'swift3'
  target 'nyx-publicTests' do
    inherit! :search_paths
    # Pods for testing
  end

end

Project that demonstrates the bug

Please add a link to a project we can download that reproduces the bug.

I can't. I don't have anything that's open source.

Simultaneous access to memory due to KVO in Xcode 9

Report a bug

What did you do?

Migrated the project to Swift 4
Ran the demo project in Xcode 9

What did you expect to happen?

No console warnings

What happened instead?

A warning in the console about simultaneous access to memory.

Simultaneous accesses to 0x7faca830da08, but modification requires exclusive access.
Previous access (a modification) started at PullToRefresh`PullToRefresh.addScrollViewObserving() + 377 (0x1013a4919).
Current access (a modification) started at:
0    libswiftCore.dylib                 0x00000001049947a0 swift_beginAccess + 505
1    PullToRefresh                      0x00000001013a0e70 PullToRefresh.contentOffsetKVOContext.materializeForSet + 38
2    PullToRefresh                      0x00000001013a1370 PullToRefresh.observeValue(forKeyPath:of:change:context:) + 185
3    PullToRefresh                      0x00000001013a4500 @objc PullToRefresh.observeValue(forKeyPath:of:change:context:) + 648
4    Foundation                         0x000000010140ccfd NSKeyValueNotifyObserver + 349
5    Foundation                         0x00000001013ed33f -[NSObject(NSKeyValueObserverRegistration) _addObserver:forProperty:options:context:] + 255
6    Foundation                         0x00000001013ec2a5 -[NSObject(NSKeyValueObserverRegistration) addObserver:forKeyPath:options:context:] + 103
7    PullToRefresh                      0x00000001013a47a0 PullToRefresh.addScrollViewObserving() + 473
8    PullToRefresh                      0x000000010139ed10 PullToRefresh.scrollView.didset + 191
9    PullToRefresh                      0x000000010139ebc0 PullToRefresh.scrollView.setter + 240
10   PullToRefresh                      0x000000010139c790 UIScrollView.addPullToRefresh(_:action:) + 125
11   PullToRefresh                      0x000000010139cec0 @objc UIScrollView.addPullToRefresh(_:action:) + 135
12   PullToRefreshDemo                  0x00000001010a3940 ViewController.setupPullToRefresh() + 485
13   PullToRefreshDemo                  0x00000001010a38a0 ViewController.viewDidLoad() + 81
14   PullToRefreshDemo                  0x00000001010a3d20 @objc ViewController.viewDidLoad() + 36
15   UIKit                              0x00000001026ac87e -[UIViewController loadViewIfRequired] + 1235
16   UIKit                              0x00000001026f4498 -[UINavigationController _updateScrollViewFromViewController:toViewController:] + 68
17   UIKit                              0x00000001026f477f -[UINavigationController _startTransition:fromViewController:toViewController:] + 153
18   UIKit                              0x00000001026f55e6 -[UINavigationController _startDeferredTransitionIfNeeded:] + 841
19   UIKit                              0x00000001026f6b1d -[UINavigationController __viewWillLayoutSubviews] + 115
20   UIKit                              0x000000010294d1c7 -[UILayoutContainerView layoutSubviews] + 231
21   UIKit                              0x00000001025dd01e -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1331
22   QuartzCore                         0x0000000109a55421 -[CALayer layoutSublayers] + 153
23   QuartzCore                         0x0000000109a59418 CA::Layer::layout_if_needed(CA::Transaction*) + 401
24   QuartzCore                         0x00000001099e2060 CA::Context::commit_transaction(CA::Transaction*) + 365
25   QuartzCore                         0x0000000109a0d8f0 CA::Transaction::commit() + 500
26   UIKit                              0x000000010252a679 __34-[UIApplication _firstCommitBlock]_block_invoke_2 + 141
27   CoreFoundation                     0x0000000102037200 __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
28   CoreFoundation                     0x000000010201b970 __CFRunLoopDoBlocks + 203
29   CoreFoundation                     0x000000010201ad00 __CFRunLoopRun + 1300
30   CoreFoundation                     0x000000010201a8f0 CFRunLoopRunSpecific + 409
31   GraphicsServices                   0x000000010931a988 GSEventRunModal + 62
32   UIKit                              0x000000010250ec91 UIApplicationMain + 159
33   PullToRefreshDemo                  0x00000001010a5c40 main + 55
34   libdyld.dylib                      0x0000000106bf1d80 start + 1

Your Environment

  • Version of the component: 2.0.2
  • Swift version: 4
  • iOS version: 11
  • Device: iPhone 8
  • Xcode version: 9 GM

Project that demonstrates the bug

Run the demo project with Xcode 9

Fix insets for UITableViewController

Hey

When used in a storyboard UITableViewController, the refresher resets the insets to .zero, causing the scroll view to go under the navigation bar and tab bar (if you have one). It should do 64 for top and 49 for bottom insets to match, but there's no way to change this.

So for some reason it's setting scrollViewDefaultInsets incorrectly, not taking into account navigation bar or tab bar.

iOS 10, Xcode 8

EDIT: I solved it by disabling "Adjust scroll view insets" and manually setting insets in viewDidLoad() - perhaps make this part of the documentation :)

Dynamic height for RefreshView

Hello,

Is there a way to create a dynamic height for the refresh view. The reason I ask is that we are looking to implement the pull to refresh functionality from here.

We have a background colour set for the table view already. The pull to refresh view background colour is different. When you drag over the height of the refresh view you see the background colour of the table view.

I was hoping it would work like the default pull to refresh where the background colour is pulled along with it. Thanks

The opposite refresher is missing

Report

It can be reproduced in PullToRefreshDemo.xcodeproj

Report a bug

What did you do?

Pull down the table view, and don't fire the action of the top refresher, and hold the finger.
Scroll up the table view rapidly.
Go to the bottom of the table view.

What did you expect to happen?

The bottom refresher is existing.

What happened instead?

The bottom refresher is missing.

Your Environment

  • Version of the component: 3.1.0
  • Swift version: 4.2
  • iOS version: iOS 12.0.1
  • Device: iPhone X
  • Xcode version: 10.0 (10A255)
  • CocoaPods: 1.5.3

Project that demonstrates the bug

The PullToRefreshDemo.xcodeproj can reproduce it.

Advice

In the override open func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) of PullToRefresher.swift, I change some code in the first if part:

In the offset switch, maybe PullToRefresh need handle the offset > 0 case:

if state != .loading && state != .finished && state != .initial { state = .initial }

Maybe it is a workaround.

[feature request] Being able to know if a PTR was initiated by the user or not.

Hey !

First, thanks for your work.

A feature request

What do you want to add?

In my case, I need to know if a refresh is initiated by the user or not. Said differently, if the user pulls, or if the application manually displayed the animation.

Why? Simple case, you want to hard-refresh the content from your API when the users pulls, but you don't want to do it when you display the PTR (because you're refreshing the content).

How should it look like?

Have a boolean in the action block.

I'll submit a PR soon!
Thanks,
Vincent

startRefreshing function failed

Report a bug

What did you do?

Drag scroll view carelessly as the image below and release when the activity indicator not completely showed up, the contentOffset become zero point again

wechatimg2

and then po the state of refresher == releasing : 0.0125

wechatimg1

so that startRefreshing function will always failed

wechatimg3

and what confused me is that enabling breakpoint at line 114 in PullToRefresh.swift, startRefreshing function worked

qq20170505-221720

`import PullToRefresh

class UuusPullToRefresh: PullToRefresh {

override init(refreshView: UIView,
              animator: RefreshViewAnimator,
              height: CGFloat,
              position: Position) {
    super.init(refreshView: refreshView,
               animator: animator,
               height: height,
               position: position)
    animationDuration = 1/4
    springDamping = 1
    initialSpringVelocity = 0
}

}`

Your Environment

  • Version of the component: Using PullToRefresher (2.0.2)
  • iOS version: 10.3.1
  • Device: iPhone 6
  • Xcode version: 8.3.2
  • If you use Cocoapods: platform :ios, '8.0' pod 'PullToRefresher'

How it works in the Auto Layout?

My Workaround

let view = pullToRefresh.refreshView
//        view.frame = CGRectMake(0, -view.frame.size.height, self.frame.size.width, view.frame.size.height)
self.addSubview(view)
view.snp_makeConstraints { (make:ConstraintMaker) -> Void in
    make.left.equalTo(self.snp_left)
    make.width.equalTo(self.snp_width)
    make.height.equalTo(view.frame.size.height)
    make.bottom.equalTo(self.snp_top)
}

Crash on deallocating

Hey, awesome library!

I am using it in a project and unfortunately experiencing a crash on deallocating. The pullToRefresh is added in viewDidAppear and is not removed manually. But as far as I see, that should not be a problem, because it should be automatically deallocated and remove the KVO observer by itself. Could you please take a look? The crash dump is:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'An instance 0x791f2400 of class UITableView was deallocated while key value observers were still registered with it. Current observation info: <NSKeyValueObservationInfo 0x79988290> ( <NSKeyValueObservance 0x79988070: Observer: 0x799875e0, Key path: contentOffset, Options: <New: NO, Old: NO, Prior: NO> Context: 0x79987634, Property: 0x79987ed0> )' *** First throw call stack: ( 0 CoreFoundation 0x02a36494 __exceptionPreprocess + 180 1 libobjc.A.dylib 0x024f0e02 objc_exception_throw + 50 2 CoreFoundation 0x02a363bd +[NSException raise:format:] + 141 3 Foundation 0x02129097 NSKVODeallocate + 353 4 UIKit 0x012b6348 -[UIView(UIKitManual) release] + 142 5 libobjc.A.dylib 0x0250334f objc_release + 47 6 libobjc.A.dylib 0x0250452d _ZN12_GLOBAL__N_119AutoreleasePoolPage3popEPv + 371 7 CoreFoundation 0x029068a8 _CFAutoreleasePoolPop + 24 8 UIKit 0x009ea9c5 _prepareForCAFlush + 370 9 UIKit 0x009f8f3d _afterCACommitHandler + 173 10 CoreFoundation 0x0294875e __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30 11 CoreFoundation 0x029486be __CFRunLoopDoObservers + 398 12 CoreFoundation 0x0293e03c __CFRunLoopRun + 1340 13 CoreFoundation 0x0293d846 CFRunLoopRunSpecific + 470 14 CoreFoundation 0x0293d65b CFRunLoopRunInMode + 123 15 GraphicsServices 0x06568664 GSEventRunModal + 192 16 GraphicsServices 0x065684a1 GSEventRun + 104 17 UIKit 0x009c6eb9 UIApplicationMain + 160 18 oozima 0x00163b71 main + 145 19 libdyld.dylib 0x03c7ea25 start + 1 ) libc++abi.dylib: terminating with uncaught exception of type NSException

Thanks!

EDIT: I think I found a solution. I was not holding a reference to the pullToRefresh itself, because I am only interested in the action. But it seems that the tableView is being deallocated before, and that produces the crash. I am removing the pull to refresh action now by myself and it's working. If you don't see an issue here, you are free to close this issue right away. Thank you!

Support refresh from the bottom?

Is it necessary to let this library support the bottom direction? I mean we make a scroll view owns two refreshers, one in the top, when user pull from top to bottom, it means to refresh the list, and another in the bottom, when user pull from bottom to top, it means to load more data.

Table cells go under Navigation bar

See image:
image

Spent a lot of time trying to debug with to luck. The only think I found is that contentOffset is not the same as before.

Before:
<UITableView: 0x7fd7908bd600; frame = (0 0; 375 667); clipsToBounds = YES; opaque = NO; autoresize = W+H; gestureRecognizers = <NSArray: 0x7fd79049e540>; layer = <CALayer: 0x7fd7904bb360>; contentOffset: {0, -64}; contentSize: {375, 82}>

After pull down to refresh:
<UITableView: 0x7fe5d9073600; frame = (0 0; 375 667); clipsToBounds = YES; opaque = NO; autoresize = W+H; gestureRecognizers = <NSArray: 0x7fe5d85aa6e0>; layer = <CALayer: 0x7fe5d8586c20>; contentOffset: {0, -40}; contentSize: {375, 82}>

scrollView.contentOffset Error

The pull up loads more,scrollView.contentOffset error. The expectation should be UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0), However, is UIEdgeInsets(top: 64.0, left: 0.0, bottom: 0.0, right: 0.0).

Inital -> Initial

You might want to fix a typo in states of animator. Is says inital instead of initial.

Merge Swift 2.0 version

Time to merge the swift 2.0 version and make a new pod version? iOS9 and Xcode 7 GM have been out for couple of weeks now.

Install 3.1.0 failed with CocoaPods

Report

I can't install PullToRefresh 3.1.0, maybe you miss set the tag and push new version to CocoaPods?

Report a bug

What did you do?

Write 'pod 'PullToRefresher', '~> 3.1' in my podfile and try to update my project

What did you expect to happen?

Success.

What happened instead?

[!] CocoaPods could not find compatible versions for pod "PullToRefresher":
In Podfile:
PullToRefresher (~> 3.1)

None of your spec sources contain a spec satisfying the dependency: PullToRefresher (~> 3.1).

You have either:

  • mistyped the name or version.
  • not added the source repo that hosts the Podspec to your Podfile.

Note: as of CocoaPods 1.0, pod repo update does not happen on pod install by default.

Your Environment

  • Xcode version: Xcode 10
  • If you use Cocoapods: 1.5.3

Add Swift 4.2 support

Report

A feature request

What do you want to add?

Possibility to work and support swift 4.2

How should it look like?

PR: #102

When i call load more func. it not show current row ?

here is my code.
call load more

func loadMore(lastOrderId:Int,rowCount:Int){
        ServiceConnector.shared.connect(.GETJOINALLOWEDINNOLIST(lastOrderId: lastOrderId, rowCount: rowCount), success: { (target, response) in
            let ex = response["err"].stringValue
            if ex.isEmpty{
                let loadMoreList:[JoinAllAllowedInno] = JoinAllAllowedInno.getJoinAllAllowedInno(json: response)
                loadMoreList.forEach({ (j) in
                    self.joinAllAllowedInnoList?.append(j)
                })
                self.joinTableView.reloadData()
            }
            else {
                self.showAlertMessage(vc: self, titleStr: "warning".localized(), messageStr: ex)
            }
            
        }) { (target, response) in
            self.hideProgressHUD()
        }
    }


**End Load more Refresh** 

self.joinTableView.addPullToRefresh(PullToRefresh(position: .bottom)) { [weak self] in
            let delayTime = DispatchTime.now() + Double(Int64(2 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
            DispatchQueue.main.asyncAfter(deadline: delayTime) {
                
                self?.loadMore(lastOrderId: (self?.joinAllAllowedInnoList?.count)!, rowCount: 1)
                self?.joinTableView.endRefreshing(at: .bottom)
            }

End refreshing animation

Would be nice if can set different types of animations for the Finished state of the refresh (not only to use spring animation).

Content offset changes after pull at bottom in iOS 11

Report a bug

What happened instead?

TableView's contentOffset changes after pull at bottom

Your Environment

  • Version of the component: 3.0.1
  • Swift version: 4.0
  • iOS version: 11.1.2
  • Device: 7
  • Xcode version: 9.2

Project that demonstrates the bug

Bug demo

[Bug]The tableView appear that contentOffset bigger

Report

Report a bug

first,run your demo,when the top refresh is working, immediately let the bottom refresh works and wait for the finished of the two refresh,you find that everytime one such operation, contentOffset become twice as large as

Environment

  • Version of the component: 2.0.2
  • Swift version: 3.0
  • iOS version: 10.3
  • Device: 6s plus
  • Xcode version: 8.3

Project that demonstrates the bug

it is your demo

Layout is off on iPhoneX if using Xcode9 and WKWebView

Report

Hi
Indicator is not center (⚭-⚭ )
See following image. On this image, changed background color for debug.
simulator screen shot - iphone x - 2017-10-06 at 18 58 21

Report a bug

What did you do?

I'll description.

  1. Installed Xcode9 GM(Version 9.0 (9A235))

  2. Clone Yalantis/PullToRefresh.

  3. Open cloned Demo project.

  4. Changed Swift Language Version to Swift 4.0 on the PullToRefreshDemo target.

  5. Changed storyboard settings:

_2017-10-06_19_13_50

  1. I did set WKWebView for your DEMO project using following source-code:
    override func viewDidLoad() {
        super.viewDidLoad()
        let wkwebview = WKWebView()
        wkwebview.navigationDelegate = self
        wkwebview.uiDelegate = self
        wkwebview.scrollView.delegate = self
        
        if #available(iOS 11.0, *) {
            wkwebview.insetsLayoutMarginsFromSafeArea = true
        }
        
        let refresher = PullToRefresh()
        wkwebview.scrollView.addPullToRefresh(refresher, action: {
            wkwebview.reloadFromOrigin()
        })
        
        let urlRequest = URLRequest(url: URL.init(string: "https://stackoverflow.com/search?q=Yalantis+PullToRefresh")!)
        
        wkwebview.load(urlRequest)
        self.view = wkwebview

And, I set the background color to orange color.

  1. And delete Table view in swift file and storyboard file.

  2. Layout is off when pulling view.

simulator screen shot - iphone x - 2017-10-06 at 18 58 21

What did you expect to happen?

I need this:
expected_simulator-screen-shot---iphone-x---2017-10-06-at-18_58_21

Or this:
expected2_simulator-screen-shot---iphone-x---2017-10-06-at-18_58_21

I used the photoshop for make this images.

What happened instead?

On left side, shown white space(layout is off) like following image:

simulator screen shot - iphone x - 2017-10-06 at 18 58 21

Your Environment

  • Version of the component: develop branch.
  • Swift version: 4.0
  • iOS version: iOS11.0.0(Simulator)
  • Device: iPhoneX
  • Xcode version: Version 9.0 (9A235)
  • If you use Cocoapods: I did not use Cocoapods.
  • If you use Carthage: I did not use Carthage.

Project that demonstrates the bug

You can download from my repository:
https://github.com/ykeisuke/PullToRefresh/tree/develop-mine

MEMO:

My private project has same problem on the iPhoneX and iOS11.

Thank you!ƪ(•ᴗ•ƪ)

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.