Skip to content

Instantly share code, notes, and snippets.

@hsavit1
Created December 1, 2015 07:35
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hsavit1/520ca852ca76c0f2209b to your computer and use it in GitHub Desktop.
Save hsavit1/520ca852ca76c0f2209b to your computer and use it in GitHub Desktop.
Using generators with tableviews in swift
protocol AsyncGeneratorType {
typealias Element
typealias Fetch
mutating func next(fetchNextBatch: Fetch, onFinish: ((Element) -> Void)?)
}
/// Generator is the class because struct is captured in asynchronous operations so offset won't update.
class PagingGenerator<T>: AsyncGeneratorType {
typealias Element = Array<T>
typealias Fetch = (offset: Int, limit: Int, completion: (result: Element) -> Void) -> Void
var offset:Int
let limit: Int
init(startOffset: Int = 0, limit: Int = 25) {
self.offset = startOffset
self.limit = limit
}
func next(fetchNextBatch: Fetch, onFinish: ((Element) -> Void)? = nil) {
fetchNextBatch(offset: offset, limit: limit) { [unowned self] (items) in
onFinish?(items)
self.offset += items.count
}
}
}
class ViewController: UIViewController {
@IBOutlet var tableView: UITableView!
private var paging = PagingGenerator<Contact>(startOffset: 0, limit: 25)
private var contacts = [Contact]() {
didSet {
tableView.reloadData()
}
}
override func viewDidLoad() {
super.viewDidLoad()
paging.next(fetchNextBatch, onFinish: updateDataSource) // first page
}
}
//MARK: Paging
extension ViewController {
private func fetchNextBatch(offset: Int, limit: Int, completion: (Array<Contact>) -> Void) -> Void {
if let remotelyFetched = downloadGithubUsersPage(offset) {
completion(remotelyFetched)
}
}
private func updateDataSource(items: Array<Contact>) {
self.contacts += items
}
}
//MARK: UITableViewDataSource
extension ViewController: UITableViewDataSource {
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return contacts.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: nil)
let contact = contacts[indexPath.row]
cell.textLabel?.text = "\(contact.firstName) \(contact.lastName)"
return cell
}
}
//MARK: UITableViewDelegate
extension ViewController: UITableViewDelegate {
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.row == tableView.dataSource!.tableView(tableView, numberOfRowsInSection: indexPath.section) - 1 {
paging.next(fetchNextBatch, onFinish: updateDataSource)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment