Swiftpack.co -  zyvv/Refresher as Swift Package
Swiftpack.co is a collection of thousands of indexed Swift packages. Search packages.
A pull-to-refresh component that can customize animation according to the pull-down state.
.package(url: "https://github.com/zyvv/Refresher.git", from: "1.0.1")


Refresher is a pull-to-refresh component that can customize animation according to the pull-down state. The core code based on MJRefresh and PullToRefresh.



  • iOS 11.0+
  • Swift 5.0+



pod 'Refresher_Swift'


github "zyvv/Refresher"

Swift Package Manager

dependencies: [
    .package(url: "https://github.com/zyvv/Refresher", .upToNextMajor(from: "1.0.0"))


Quick Start

If you installed via CocoaPods:

import Refresher_Swift


import Refresher


class MyViewController: UICollectionViewController {
    override func viewDidLoad() {

        // pull-down refresh
        collectionView.topRefresher = Refresher {
            // fetchLatestData()
        // pull-up refresh
        collectionView.bottomRefresher = Refresher {
            // fetchData(page: Int)

Trigger Refresher to refreshing with code:


End Refresher refreshing:


Disable Refresher:

collectionView.topRefresher?.isEnable = false


At first, Create a custom view that conforms Refreshable protocol:

class CustomAnimateView: UIView, Refreshable {

    func animate(_ state: Refresher.State) {
        switch state {

        // Idle state. Back to the initial state.
        case .idle: idleState()

        // Animation being pulled down.
        // progress: 0 -> 1
        case .pulling(let progress): pullingAnimation(progress)

        // Animation to be refreshed.
        // overOffset: The pull-down offset of the scrollview in this state.
        case .willRefresh(let overOffset): willRefreshAnimation(overOffset)
        // Animation being refreshed.
        case .refreshing: refreshingAnimation()
        // Rebound animation after refresh.
        // progress: 0 -> 1
        case .rebounding(let progress): pullingAnimation(1-progress)

Then, initialize Refresher:

collectionView.topRefresher = Refresher(CustomAnimateView()) {
    // fetchLatestData()

Pull-up to Load More

The difference with pull-down refresh is that the state of pull-up refresh is directly from .idle to .refreshing after bottomRefresher appears.

Pull-up refresh can be ended like pull-down refresh, or a no-more-data view can be added after the end. After the view is added, bottomRefresher will be disabled.

func noMoreLabel() -> UILabel {
    let label = UILabel()
    label.text = "No More Data."
    label.textColor = .placeholderText
    label.textAlignment = .center
    label.font = UIFont.systemFont(ofSize: 12)
    label.frame.size.height = 30
    return label

func endRefreshing(count: Int) {
    collectionView.bottomRefresher?.endRefreshing(count == 0 ? noMoreLabel() : nil)


Refresher is released under the MIT license. See LICENSE for details.


Stars: 0
Last commit: 4 weeks ago

Ad: Job Offers

iOS Software Engineer @ Perry Street Software
Perry Street Software is Jack’d and SCRUFF. We are two of the world’s largest gay, bi, trans and queer social dating apps on iOS and Android. Our brands reach more than 20 million members worldwide so members can connect, meet and express themselves on a platform that prioritizes privacy and security. We invest heavily into SwiftUI and using Swift Packages to modularize the codebase.

Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API