Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@nemotoo
Last active August 29, 2015 14:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nemotoo/36394830b8e03509c47f to your computer and use it in GitHub Desktop.
Save nemotoo/36394830b8e03509c47f to your computer and use it in GitHub Desktop.
Seamless Infinite UITableView with double page data
// Reference - Main : http://stackoverflow.com/questions/18164519/uitableview-inserting-section-at-top-while-scrolling
// Reference - Sub : http://bharath2020.in/2012/10/01/uitableview-tricks-part-2-infinite-scrolling/
import UIKit
class SeamlessInfiniteTableViewController: UITableViewController {
/* Variables */
let FetchingCount = 10 //WARNING : Below 10 is not recommened and tested
var mergedSections:[[String]] = [] //WARNING : Every section has more than 0 row
/* */
/* Private */
var numOfBackItems = 0
var backSections:[[String]] = []
var numOfFrontItems = 0
var frontSections:[[String]] = []
/* */
/* Debug */
let numOfDummySections = 3
let numOfDummyRows = 5
/* */
var page = INT_MAX{
didSet{
if page == oldValue {
return
}else if page - 1 == oldValue{
//Next Page
println("Next Page")
backSections = frontSections
numOfBackItems = numOfFrontItems
loadFrontItems()
}else if page + 1 == oldValue {
// Previous Page
println("Previous page")
frontSections = backSections
numOfFrontItems = numOfBackItems
loadBackItems()
}else{
println("Load all pages")
loadBackItems()
loadFrontItems()
}
mergedSections = backSections + frontSections
}
}
override func viewDidLoad() {
super.viewDidLoad()
page = 0
if mergedSections.count == 0{
return
}
var initialSection = backSections.count // Last index of backSections + 1
var initialRow = 0
if frontSections.count == 0 {
initialSection = backSections.count - 1
initialRow = backSections.last!.count - 1
}
var initialIndexPath = NSIndexPath(forRow: initialRow, inSection: initialSection)
tableView.scrollToRowAtIndexPath(initialIndexPath, atScrollPosition: UITableViewScrollPosition.Top, animated: false)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prefersStatusBarHidden() -> Bool {
return true
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return mergedSections.count
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return mergedSections[section].count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! UITableViewCell!
cell.textLabel!.text = mergedSections[indexPath.section][indexPath.row]
return cell
}
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return mergedSections[section][0]
}
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
if (tableView.contentSize.height < tableView.frame.size.height) {
println("TableView is smaller than frame")
return
}
var visibleIndexPaths = tableView.indexPathsForVisibleRows() as! [NSIndexPath]
if visibleIndexPaths.count == 0{
println("TableView has no visiable rows")
return
}
var pageStepper = 0
// 1. Check Top
if indexPath.section == 0 && indexPath.row == 0{
if numOfBackItems < FetchingCount{
println("[Top] There is no previous items")
return
}
println("[Top] Load previous page")
pageStepper = -1
}
// 2. Check Bottom
else if indexPath.section == (mergedSections.count - 1) && indexPath.row == (mergedSections.last!.count - 1){
if numOfFrontItems < FetchingCount{
println("[Bottom] There is no next items")
return
}
println("[Bottom] Load next page")
pageStepper = 1
}
if pageStepper == 0{
return
}
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.page += pageStepper
var oldIndexPath = indexPath
var before = self.tableView.rectForRowAtIndexPath(oldIndexPath)
var contentOffset = self.tableView.contentOffset
self.tableView.reloadData()
var newIndexPath = NSIndexPath(forRow: oldIndexPath.row, inSection: oldIndexPath.section - pageStepper)
var after = self.tableView.rectForRowAtIndexPath(newIndexPath)
contentOffset.y += (after.origin.y - before.origin.y);
self.tableView.contentOffset = contentOffset
})
}
//MARK: - Private
func loadBackItems(){
backSections = []
//Load dummy back items
for s in 0..<numOfDummySections{
var section:[String] = []
for r in 0 ..< numOfDummyRows{
section.append(("[Page \(page - 1)]\(s) / \(r)"))
}
backSections.append(section)
}
numOfBackItems = countItems(backSections)
}
func loadFrontItems(){
frontSections = []
//Load dummy front items
for s in 0..<numOfDummySections{
var section:[String] = []
for r in 0 ..< numOfDummyRows{
section.append(("[Page \(page)]\(s) / \(r)"))
}
frontSections.append(section)
}
numOfFrontItems = countItems(frontSections)
}
func countItems(twoDimensionArray:[[String]]) -> Int{
var count = 0
for ar in twoDimensionArray{
count += ar.count
}
return count
}
}
@nemotoo
Copy link
Author

nemotoo commented Apr 26, 2015

I recommend to use JTTableViewController

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment