CloudKit: Query returns partial results, no errors

318 views Asked by At

I have some kind of CloudKit indexing issue. When I save records to iCloud using CKModifyRecordsOperation, modifyRecordsCompletionBlock returns no errors. When I query those records using NSPredicate(value: true) or Dashboard, most of the time it misses one or two records.

So say I upload 5 records (no errors), wait some time (~15 secs) to make sure that indexes are updated, and then query them (through dashboard or app's CKQueryOperation). Most of the time it will show 4 records out 5. Again, no errors. Records are in privateDB in customZone.

Here is what's strange: I'm always able to get records that query didn't return by manually typing recordNames in Dashboard (development) under 'Fetch' menu. So it stores them, just doesn't query. When I delete indexes in a dashboard and reassign them, dashboard query will start to return all the results (with previously omitted records too), but after a few more uploads, some will start to be missing from query again.

Here is my CKModifyRecordsOperation:

let operation = CKModifyRecordsOperation(recordsToSave: records, recordIDsToDelete: []) 

operation.modifyRecordsCompletionBlock =
{ [weak self] savedRecords, deletedRecordIDs, error in

   guard error == nil else { // no errors here ... } 
   ...
   //for each item uploaded to iCloud, mark as synced
   if let savedRecords = savedRecords{ // all attempted to save records are here
        PendingCloudOperations.shared.markAsUploaded(
        savedRecords.map{ $0.recordID.recordName })
   }

   completion(...)
}

operation.savePolicy = .changedKeys          // tried .allKeys too
operation.qualityOfService = .userInitiated  

self.privateDB.add(operation)

I experimented with record fields (originally date, asset, and reference) trying to see if any of the fields make a problem. But even if I remove all field's (creating a record with no extra fields, just system meta), problem persists. I didn't include CKQueryOperation code, because Dashboard acts same way as the app.

Any ideas?

EDIT: Here are bare-bones of my fetching function:

    var receipts:[FS_Receipt] = []

    let query = CKQuery(recordType: myRecordType, predicate: NSPredicate(value: true))
    let operation = CKQueryOperation(query: query)

    //completion block
    operation.queryCompletionBlock = { [weak self] cursor, error in
        guard error == nil else {
            // doesn't have any errors here
        }

        completion(...) 
    }

    operation.recordFetchedBlock = { record in

        // doesn't return all records here most of the time.
    }



    operation.qualityOfService = .userInitiated // without this, 'no internet' will NOT return error

    operation.resultsLimit = 5000 

    operation.zoneID = customZoneID


    self.privateDB.add(operation)
}
0

There are 0 answers