1

In the app i am making, there will be a lot of data for the app to load from iCloud. My problem is that it does not load the data into a collection view until its finished receiving all the data(which takes a while). I want the app to load the data onto the collection view as its receiving the data, so the user does not have to wait. Or is it better to have the app only load some of the data at a time? How do i do this? Here is my code that i am using to load the data.

Note: I am using swift for this project.

  func loadInfo() {

        let predicate:NSPredicate = NSPredicate(value: true)
        let query:CKQuery = CKQuery(recordType: "Data", predicate: predicate)
        query.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]




        if let database = self.publicDatabase {


            database.performQuery(query, inZoneWithID: nil, completionHandler: { (records:[AnyObject]!, error:NSError!) in

                if error != nil {

self.alert("Error: \(error.localizedDescription)", Message: "Make sure iCloud is turned on and you are connected to the internet")

                }
                else {



                    dispatch_async(dispatch_get_main_queue()) {

                        self.array.removeAll(keepCapacity: false)

                        for record in records {

                            let usernameRecord:CKRecord = record as CKRecord
                            self.array.append(usernameRecord.objectForKey("Info") as String)





                        }

                        //update data
                        self.collectionView.reloadData()

                    }


                }

                })

            }}
nachshon f
  • 3,540
  • 7
  • 35
  • 67

1 Answers1

5

if you do a performQuery, the records will be returned all at once. If you want progress, then you can use the CKQueryOperation. You will then get a call for each record for the block:

 operation.recordFetchedBlock = { record in

When the query is ready, then there will be a call to.

operation.queryCompletionBlock = { cursor, error in

The number of records returned will be limited to a maximum (usually 100). That value can be set by using:

operation.resultsLimit = CKQueryOperationMaximumResults;

Just set it to the value you want.

Here is a sample that is based on the link from the comment below:

func loadInfo() {

    let p = NSPredicate(value: true)
    let q = CKQuery(recordType: "Data", predicate: p)
    q.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
    let queryOperation = CKQueryOperation(query: q)
    let database = self.publicDatabase
    self.array.removeAll(keepCapacity: false)

    queryOperation.recordFetchedBlock = fetchedARecord

    queryOperation.queryCompletionBlock = { [weak self] (cursor : CKQueryCursor!, error : NSError!) in
        if error != nil {
            self.alert("Error: \(error.localizedDescription)", Message: "Make sure iCloud is turned on and you are connected to the internet")
        }
        else {
        if cursor != nil {
            println("there is more data to fetch")
            let newOperation = CKQueryOperation(cursor: cursor)
            newOperation.recordFetchedBlock = self!.fetchedARecord
            newOperation.queryCompletionBlock = queryOperation.queryCompletionBlock
            database.addOperation(newOperation)
            }
        } else {
            dispatch_async(dispatch_get_main_queue()) {
                self.collectionView.reloadData()
            }
        }

    }

    database.addOperation(queryOperation)
}

var i = 0
func fetchedARecord (record: CKRecord!) {
    println("\(NSDate().timeIntervalSinceReferenceDate*1000) \(++i)")
    self.array.append(record.objectForKey("Info") as String)
}
Edwin Vermeer
  • 13,017
  • 2
  • 34
  • 58
  • nachson fertel, see the link above from CPPChase for the sample code – Edwin Vermeer Apr 13 '15 at 06:20
  • I saw the link, but its not a good example. Can you give me an example for the code i showed in the question? – nachshon f Apr 13 '15 at 12:24
  • A added a sample to the answer. It's a quick merge from the example from the link above with your code. I hope I did not make any mistakes since it's untested. – Edwin Vermeer Apr 13 '15 at 12:41
  • Use this http://stackoverflow.com/questions/31503184/ckqueryoperation-querycompletionblock-only-runs-3-times/31664231#31664231the above only runs I think 3 times. – DogCoffee Apr 12 '16 at 13:26