• Stars
    star
    1,059
  • Rank 43,570 (Top 0.9 %)
  • Language
    Objective-C
  • License
    MIT License
  • Created about 11 years ago
  • Updated about 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

UIScrollView ∞ scroll category

UIScrollView+InfiniteScroll

Infinite scroll implementation as a category for UIScrollView.

* The content used in demo app is publicly available and provided by hn.algolia.com and Flickr. Both can be inappropriate.

Swizzling

Be aware that this category swizzles setContentOffset and setContentSize on UIScrollView.

Swift Package Manager

Add new package using github repo URL:

https://github.com/pronebird/UIScrollView-InfiniteScroll

Then import module in the source code:

import UIScrollView_InfiniteScroll

CocoaPods

Add the following line in your Podfile:

pod 'UIScrollView-InfiniteScroll', '~> 1.3.0'

Objective-C

#import <UIScrollView_InfiniteScroll/UIScrollView+InfiniteScroll.h>

or if using modules:

@import UIScrollView_InfiniteScroll;

Swift

Add the following line in your bridging header file:

#import <UIScrollView_InfiniteScroll/UIScrollView+InfiniteScroll.h>

Carthage

Add the following line in your Cartfile:

github "pronebird/UIScrollView-InfiniteScroll" ~> 1.3.0

Objective-C

#import <UIScrollView_InfiniteScroll/UIScrollView+InfiniteScroll.h>

or if using modules:

@import UIScrollView_InfiniteScroll;

Swift

import UIScrollView_InfiniteScroll

Examples

This component comes with example app written in Swift.

If you use CocoaPods you can try it by running:

pod try UIScrollView-InfiniteScroll

Documentation

http://pronebird.github.io/UIScrollView-InfiniteScroll/

Basics

In order to enable infinite scroll you have to provide a handler block using addInfiniteScrollWithHandler. The block you provide is executed each time infinite scroll component detects that more data needs to be provided.

The purpose of the handler block is to perform asynchronous task, typically networking or database fetch, and update your scroll view or scroll view subclass.

The block itself is called on main queue, therefore make sure you move any long-running tasks to background queue. Once you receive new data, update table view by adding new rows and sections, then call finishInfiniteScroll to complete infinite scroll animations and reset the state of infinite scroll components.

viewDidLoad is a good place to install handler block.

Make sure that any interactions with UIKit or methods provided by Infinite Scroll happen on main queue. Use dispatch_async(dispatch_get_main_queue, { ... }) in Objective-C or DispatchQueue.main.async { ... } in Swift to run UI related calls on main queue.

Many people make mistake by using external reference to table view or collection view within the handler block. Don't do this. This creates a circular retention. Instead use the instance of scroll view or scroll view subclass passed as first argument to handler block.

Objective-C

// setup infinite scroll
[tableView addInfiniteScrollWithHandler:^(UITableView* tableView) {
    // update table view
    
    // finish infinite scroll animation
    [tableView finishInfiniteScroll];
}];

Swift

tableView.addInfiniteScroll { (tableView) -> Void in
    // update table view
            
    // finish infinite scroll animation
    tableView.finishInfiniteScroll()
}

Collection view quirks

UICollectionView.reloadData causes contentOffset to reset. Instead use UICollectionView.performBatchUpdates when possible.

Objective-C

[self.collectionView addInfiniteScrollWithHandler:^(UICollectionView* collectionView) {    
    [collectionView performBatchUpdates:^{
        // update collection view
    } completion:^(BOOL finished) {
        // finish infinite scroll animations
        [collectionView finishInfiniteScroll];
    }];
}];

Swift

collectionView.addInfiniteScroll { (collectionView) -> Void in
    collectionView.performBatchUpdates({ () -> Void in
        // update collection view
    }, completion: { (finished) -> Void in
        // finish infinite scroll animations
        collectionView.finishInfiniteScroll()
    });
}

Start infinite scroll programmatically

You can reuse infinite scroll flow to load initial data or fetch more using beginInfiniteScroll(forceScroll). viewDidLoad is a good place for loading initial data, however absolutely up to you to decide that.

When forceScroll parameter is true, Infinite Scroll component will attempt to scroll down to reveal indicator view. Keep in mind that scrolling will not happen if user is interacting with scroll view.

Objective-C

[self.tableView beginInfiniteScroll:YES];

Swift

tableView.beginInfiniteScroll(true)

Prevent infinite scroll

Sometimes you need to prevent the infinite scroll from continuing. For example, if your search API has no more results, it does not make sense to keep making the requests or to show the spinner.

Objective-C

[tableView setShouldShowInfiniteScrollHandler:^BOOL (UITableView *tableView) {
    // Only show up to 5 pages then prevent the infinite scroll
    return (weakSelf.currentPage < 5);
}];

Swift

// Provide a block to be called right before a infinite scroll event is triggered. 
// Return YES to allow or NO to prevent it from triggering.
tableView.setShouldShowInfiniteScrollHandler { _ -> Bool in
    // Only show up to 5 pages then prevent the infinite scroll
    return currentPage < 5 
}

Seamlessly preload content

Ideally you want your content to flow seamlessly without ever showing a spinner. Infinite scroll offers an option to specify offset in points that will be used to start preloader before user reaches the bottom of scroll view.

The proper balance between the number of results you load each time and large enough offset should give your users a decent experience. Most likely you will have to come up with your own formula for the combination of those based on kind of content and device dimensions.

// Preload more data 500pt before reaching the bottom of scroll view.
tableView.infiniteScrollTriggerOffset = 500;

Custom indicator

You can use custom indicator instead of default UIActivityIndicatorView.

Custom indicator must be a subclass of UIView and implement the following methods:

@objc func startAnimating()
@objc func stopAnimating()

Swift

let frame = CGRect(x: 0, y: 0, width: 24, height: 24)
tableView.infiniteScrollIndicatorView = CustomInfiniteIndicator(frame: frame)

Please see example implementation of custom indicator view:

At the moment InfiniteScroll uses indicator's frame directly so make sure you size custom indicator view beforehand. Such views as UIImageView or UIActivityIndicatorView will automatically resize themselves so no need to setup frame for them.

Contributors

Please see CHANGES

Attributions

Demo app icon by PixelResort.

More Repositories

1

CustomModalTransition

Custom transitions on iOS 7 and iOS 8
Objective-C
84
star
2

PBPopinController

Custom container controller with keyboard-like presentation
Objective-C
15
star
3

pomo-iphone

Gettext translations for iOS
Objective-C
13
star
4

UICollectionView-NSFetchedResultsController

A simple category on UICollectionView to perform content changes in UITableView fashion. Comes handy with NSFetchedResultsController.
Objective-C
9
star
5

InputViewController

Sample app using UIInputViewController
Objective-C
7
star
6

PBImageStorage

Key-value image storage with memory cache, thumbnails support and on-disk persistence.
Objective-C
7
star
7

CollectionViewCheckbox

A sample project with checkbox support in collection views
Objective-C
5
star
8

MemeBotFB

Got sick of your pals clogging your Facebook feed with cats, wisdom pictures and inspirational quotes? It's time for revenge, increase the relevance of your feed by automatically posting fresh Meme a day.
JavaScript
5
star
9

wp-clanwars

WordPress content management plugin for e-sports teams and gaming communities
PHP
5
star
10

operation.js

NSOperations in Javascript 😲
TypeScript
4
star
11

TableViewTest

Simple table view controller with automatic row height
Objective-C
3
star
12

InteractiveNotification

Test project featuring interactive notifications with text input on iOS 9
Objective-C
3
star
13

NSOperationReproducingRaceCondition

Objective-C
2
star
14

RangeSlider

Range slider for iOS built with Autolayout.
Objective-C
2
star
15

Button

UIButton replica with better subclassing capabilities
Objective-C
2
star
16

node-rust-zeromq

Rust server/Node client using ØMQ and Protobuf / example app
Rust
2
star
17

ActivityIndicator

Custom activity indicator implementation
Objective-C
2
star
18

UIkitBugScrollViewSwift

Reproducing scroll view bug https://github.com/pronebird/UIScrollView-InfiniteScroll/issues/16
Swift
1
star
19

FlipRootController

Sample project that demonstrates the flip between root controllers using UIView.transitionFromView:toView:..
Objective-C
1
star
20

SimpleLogging

Simple logging system implementation as a coding exercise
Swift
1
star
21

HalfModalContainerController

An attempt to rewrite PBPopinController as view controller
Objective-C
1
star
22

IAPExample

An example IAP app
Objective-C
1
star
23

TabBarOrientationExample

A sample app to demo orientation lock on one of tabs in TabBarController
Objective-C
1
star
24

NSString-NSStringDrawingCompatibility

iOS 7 NSStringDrawing API compatible with iOS 6
Objective-C
1
star