Search code examples
swiftcloudkit

load more records on scroll down


The loadPost function will load 12 records initially with the resultsLimit of the query operation. The next 12 records will load in cursor to call the rest of the batch with a limit of 12 again.

My question is how do I load that next 12 records only after the view is scrolled down?

import UIKit
import CloudKit

class homesVC: UICollectionViewController {

var app : [CKRecord]
var backgroundQueue : NSOperationQueue

required init?(coder aDecoder: NSCoder) {
    app = []
    backgroundQueue = NSOperationQueue()
    super.init(coder: aDecoder)
}

var refresher: UIRefreshControl!
var page: Int = 12

var uuidArray = [String]()
var picArray = [CKAsset]()


override func viewDidLoad() {
    super.viewDidLoad()

    //pull to refresh
    refresher = UIRefreshControl()
    refresher.addTarget(self, action: #selector(homesVC.refresh), forControlEvents: UIControlEvents.ValueChanged)
    collectionView?.addSubview(refresher)


    //load posts func
    loadPosts()
}

//load posts func
func loadPosts(){
        let container = CKContainer.defaultContainer()
        let database = container.publicCloudDatabase
        let predicate = NSPredicate(value: true)
        let query = CKQuery(recordType: "posts", predicate: predicate))
        let queryOperation = CKQueryOperation(query: query)
        queryOperation.resultsLimit = 12
        queryOperation.recordFetchedBlock = {
            record in

                self.app.append(record)
                self.uuidArray.append(record.valueForKey("uuid") as! String)
                self.picArray.append(record.valueForKey("pic") as! CKAsset)
                NSOperationQueue.mainQueue().addOperationWithBlock(){
                self.collectionView?.reloadData()
            }
        }

        queryOperation.queryCompletionBlock = {
            cursor, error in
            if error != nil {
                print(error!.localizedDescription)
            } else{
                if cursor != nil {

                    self.loadMore(cursor!)
                    }
                }
            }
        }
        cloudKitCentral.publicDatabase.addOperation(queryOperation)
    }

override func scrollViewDidScroll(scrollView: UIScrollView) {
    if scrollView.contentOffset.y >= scrollView.contentSize.height - self.view.frame.size.height{

    }
}

func loadMore(cursor: CKQueryCursor){

    let queryOperation = CKQueryOperation(cursor: cursor)
    queryOperation.resultsLimit = 12
    queryOperation.recordFetchedBlock = {
        record in
        self.app.append(record)
        self.uuidArray.append(record.valueForKey("uuid") as! String)
        self.picArray.append(record.valueForKey("pic") as! CKAsset)
    }
    queryOperation.queryCompletionBlock = {
        cursor, error in
        if error != nil {
            print(error?.localizedDescription)
        } else {
            if cursor != nil {
                print("total records: \(self.app.count)")
                self.loadMore(cursor!)
            } else {
                print("completed query")
                NSOperationQueue.mainQueue().addOperationWithBlock(){
                    self.collectionView?.reloadData()
                }
            }
        }
    }
    container.publicDatabase.addOperation(queryOperation)
  }

Solution

  • Andrew,

    You have stumbled across one of the most interesting aspects of using cloud kit, that is programming with latency and threading. To achieve your goal you need to use a facility like blocks of grand central dispatch.

    Using one or the other you launch a second tread at the same time you do your initial query to continue to the load/preload more/post check loads are complete.

    I posted a blocks operation template the other week, here.

    How to determine when all images have been downloaded from a set in Swift?

    Don't let your user in the meantime scroll unless your ready; if they try to give them a nice friendly message telling them your waiting for cloudkit to give you the data.