Code Monkey home page Code Monkey logo

swiftpaginator's Introduction

SwiftPaginator

CocoaPods CocoaPods CocoaPods Travis branch CocoaPods Carthage compatible ๐Ÿง Linux Ready

Paging

SwiftPaginator is a block-based Swift class that helps manage paginated resources. Inspired by NMPaginator, an Obj-C class. SwiftPaginator leverages blocks and generics so that subclassing and delegates aren't needed.

Features

  • Written in Swift
  • Uses Generics, No Subclassing required.
  • Block based, no delegate required.
  • 100% Test Coverage
  • Fully Documented
  • iOS | OSX | WatchOS | tvOS | Linux tested & ready
  • Cocoapods installable
  • Carthage installable
  • Swift Package Manager installable

How to Install

Cocoapods (OS X)

Add this to your Podfile:

pod 'SwiftPaginator', '~> 1.0.0'

and run

$> pod install # (or update)

Carthage (OS X)

Add this to your Cartfile

github "apocolipse/SwiftPaginator" ~> 1.0.0

and run

$> carthage update # (bootstrap|build)

Swift Package Manager (OS X + Linux)

You can use The Swift Package Manager to install SwiftPaginator by adding the proper description to your Package.swift file:

import PackageDescription

let package = Package(
    name: "YOUR_PROJECT_NAME",
    targets: [],
    dependencies: [
        .Package(url: "https://github.com/apocolipse/SwiftPaginator.git", versions: "1.0.0" ..< Version.max)
    ]
)

Note that the Swift Package Manager is still in early design and development, for more infomation checkout its GitHub Page

Manually

Copy SwiftPaginator.swift to your project

How to use

Although based on NMPaginator, SwiftPaginator doesn't require subclassing or delegates. The Paginator class uses Generics and Blocks to handle everything for you.

Set up a Paginator

import SwiftPaginator

let source = [["one", "two"], ["three", "four"]]

Simple example:

let stringPaginator = Paginator<String>(pageSize: 2, fetchHandler: { (paginator, page, pageSize) in
    paginator.receivedResults(source[page], total: 4)
}, resultsHandler: { (_, _) in
    self.tableView.reloadData()
})

A more complete example:

let stringPaginator = Paginator<String>(pageSize: 2, fetchHandler: {
      (paginator: Paginator, page: Int, pageSize: Int) in

      // implement how to fetch results, must call paginator.receivedResults(_:total:) or paginator.failed()
      if page < source.count {
        paginator.receivedResults(source[page], total: 4)
      } else {
        paginator.failed()
      }

    }, resultsHandler: { (paginator, results) in
        // Handle results
        print(results) // results for the given page
        print(paginator.results) // all results

    }, resetHandler: { (paginator) in
        // callback for a reset, Optional
        tableView.reloadData()
    }, failureHandler: { (paginator) in
        // callback for a failure, Optional
        self.presentFailureAlert()
    })
Setting up in a View Controller

Declare the property

class ViewController: UIViewController {
    var stringPaginator: Paginator<String>?
...

Be sure to call fetchFirstPage() in viewDidLoad(), use fetchNextPage() elsewhere when you need to load more results (i.e. when scrolling to the bottom of a scroll view or tapping a button)

override func viewDidLoad() {
    super.viewDidLoad()
    stringPaginator = ...
    stringPaginator.fetchFirstPage()
}

func loadMoreResults() {
    stringPaginator.fetchNextPage()
}

Fetch pages

Use fetchFirstPage() or fetchNextPage() to invoke a fetch. fetchFirstPage() calls reset() then fetchNextPage() internally.

stringPaginator.fetchNextPage()  // Use this one for most cases
stringPaginator.fetchFirstPage() // will reset paginator

Details on how to define fetch behavior below in fetchHandler NOTE: Paginator will not allow simultaneous requests. Requests incoming while paginator.requestStatus is .InProgress will be ignored.

Reset the paginator

To reset the paginator and clear all stored results, simply call:

stringPaginator.reset()

Details on the resetHandler below show how to react to a reset()

Status

The requestStatus property stores an enum of type RequestStatus with 3 cases, .Done, .InProgress, .None. Until the 1st page is fetched, the status is .None, after which it will be .InProgress while async requests are processing and .Done otherwise.

Blocks Explained

All blocks have a paginator: Paginator<T> parameter, this is a reference to self called within the paginator so you may use it within the block without scope issues. All blocks passed in the init method can be accessed and changed after initialization, i.e.

paginator.fetchHandler   = ...
paginator.resultsHandler = ...
paginator.resetHandler   = ...
paginator.failureHandler = ...

fetchHandler - Required

The fetchHandler block defines the behavior to fetch new pages. It is called internally from fetchNextPage(). NOTE: You Must call either paginator.receivedResults(_:total:) or paginator.failed() within the fetchHandler.

paginator.fetchHandler = {
    (paginator, page, pageSize) in

    APIClient.getResources() { (response, failure) in
        if failure {
            paginator.failed()
        } else {
            paginator.receivedResults(response.results, total: response.total)
        }
    }
}

resultsHandler - Required

The resultsHandler allows you to handle batches of new results coming in. Although it is required to be defined, it can be empty, i.e.

...
resultsHandler: { (_, _) in },
...

But usually will be used to notify the View Controller to update the UI

...
resultsHandler: { (paginator, results) in
    self.handleNewResults(results)
    self.tableView.reloadData()
},
...

NOTE: the results passed to the resultsHandler are the results for that specific page, to access all results use paginator.results

resetHandler - Optional

The resetHandler allows you to do things like updating the UI or other activities that must be done after the data source has changed. It is optional.

paginator.resetHandler = {
    (paginator) in
    self.tableView.reloadData()
}

failureHandler - Optional

The failureHandler allows you to react to failures separately from the fetchHandler. It isn't required, but is a decent way to split logic of fetching and reacting to failures.

paginator.resetHandler = {
    (paginator) in
    self.presentFailedAlert()
}

swiftpaginator's People

Contributors

apocolipse avatar mpsnp avatar

Watchers

James Cloos avatar  avatar

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.