CloudKit record exists (added days ago), does not get returned by query but can be fetched by ID

I have a situation where a CloudKit record is not being returned by a query (and also doesn't appear in the CloudKit dashboard), but it exists when fetching it by it's ID.


The record was added days ago, so it really should have been indexed.


The record ID metadata index has always been set for the record type.


The query I use is fetching all records for a particular record type in a custom zone.


Strangely, when I search for the record in the dashboard and select it, the record name field is blank on the detail panel.


It's very peculiar, and very concerning!


Anyone have any ideas?

Replies

Show us your code for the original save, the fetch and the query. Include the specifications for the CKRecordZoneID, CKQuery, NSPredicate, CKDatabase, CKContainer and CKRecordID for the query and the fetch and the original save command (CKModifyRecordsOperation?).

I should say that most other records work absolutely fine. This is an anomaly with a handful of records. All records were created days ago and there should be nothing special about the ones that are missing. They have just suddently started to not be returned.


Here's is some very stripped down code that is used to save and query the data:


let defaultContainer = CKContainer(identifier: "iCloud.com.company.app")
let privateDatabase = defaultContainer.privateCloudDatabase
let operationQueue = NSOperationQueue()
let recordZoneID = CKRecordZoneID(zoneName: "AttachmentsZone", ownerName: CKOwnerDefaultName)
let attachmentRecordType = "Attachment"

//
// Save
//

// Create attachment record
let recordID = CKRecordID(recordName: "attachment1.jpg", zoneID: recordZoneID)
let attachmentRecord = CKRecord(recordType: attachmentRecordType, recordID: recordID)
// ... Set other attributes

// Save operation
let operation = CKModifyRecordsOperation(recordsToSave: [attachmentRecord], recordIDsToDelete: [AnyObject]())
operation.database = privateDatabase
operation.atomic = false // Allow certain saves to fail and others succeed
operation.modifyRecordsCompletionBlock = { (savedRecords: [AnyObject]!, deletedRecordIDs: [AnyObject]!, error: NSError?) in
    if let error = error {
        // Failed
    } else {
        // Success
    }
}
operationQueue.addOperation(operation)

//
// Fetch By Record ID
//

privateDatabase.fetchRecordWithID(CKRecordID(recordName: "attachment1.jpg", zoneID: recordZoneID), completionHandler: { (record: CKRecord?, error: NSError?) -> Void in
    // Record fetched successfully, so it definitely exists!
})

//
// Query (Should return everything, but doesn't!)
//

private func fetchCloudAttachmentsFilenames(cursor: CKQueryCursor? = nil, previousFileNames: Set<String>? = nil, completion: (fileNames: Set<String>?, error: NSError?) -> Void) {
    // Fetch names
    var fileNames = previousFileNames ?? Set<String>()
    let operation: CKQueryOperation
    if let cursor = cursor {
        operation = CKQueryOperation(cursor: cursor)
    } else {
        operation = CKQueryOperation(query: CKQuery(recordType: attachmentRecordType, predicate: NSPredicate(value: true)))
        operation.zoneID = recordZoneID
    }
    operation.database = privateDatabase
    operation.desiredKeys = [] // We only need recordID
    operation.recordFetchedBlock = { (record: CKRecord!) -> Void in
        fileNames.insert(record.recordID.recordName)
    }
    operation.queryCompletionBlock = { (cursor: CKQueryCursor?, error: NSError?) -> Void in
        if let cursor = cursor where error == nil {
            // More results
            self.fetchCloudAttachmentsFilenames(cursor: cursor, previousFileNames: fileNames, completion: completion)
        } else if let error = error where error.code != CKErrorCode.UnknownItem.rawValue {
            // Error but ignoring unknown item type (it means no record type yet as there are no items)
            completion(fileNames: nil, error: error)
        } else {
            // No more results so we have them all
            // BUT "attachment1.jpg" DOES NOT EXIST
            if !fileNames.contains("attachment1.jpg") {
                // FAILED TO RETURN EXISTING RECORD
            }
            completion(fileNames: fileNames, error: nil)
        }
    }
    operationQueue.addOperation(operation)
}

I get exactly the same issue. Record doesn't appear in dashboard or fetching by query. But when I fetch by recordName, it exists.

Same for me. The record doesn't appear in the dashboard or fetching by query although that the fields I'm querying by have the QUERYABLE indexes added, but when I fetch by recordName, it exists.

Is this still an issue?

Yes I just noticed this issue, it seems like sometimes the query results are cached.

What worked for me:

  1. Query some other entity and get the results
  2. Then go back to your interested entity and query again (hopefully you should see the record changes)